home *** CD-ROM | disk | FTP | other *** search
/ Aminet 48 / Aminet 48 (2002)(GTI - Schatztruhe)[!][Apr 2002].iso / Aminet / text / edit / vim60src.lha / Vim / vim60 / src / edit.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-09-24  |  166.1 KB  |  7,071 lines

  1. /* vi:set ts=8 sts=4 sw=4:
  2.  *
  3.  * VIM - Vi IMproved    by Bram Moolenaar
  4.  *
  5.  * Do ":help uganda"  in Vim to read copying and usage conditions.
  6.  * Do ":help credits" in Vim to see a list of people who contributed.
  7.  * See README.txt for an overview of the Vim source code.
  8.  */
  9.  
  10. /*
  11.  * edit.c: functions for Insert mode
  12.  */
  13.  
  14. #include "vim.h"
  15.  
  16. #ifdef FEAT_INS_EXPAND
  17. /*
  18.  * definitions used for CTRL-X submode
  19.  */
  20. #define CTRL_X_WANT_IDENT    0x100
  21.  
  22. #define CTRL_X_NOT_DEFINED_YET    1
  23. #define CTRL_X_SCROLL        2
  24. #define CTRL_X_WHOLE_LINE    3
  25. #define CTRL_X_FILES        4
  26. #define CTRL_X_TAGS        (5 + CTRL_X_WANT_IDENT)
  27. #define CTRL_X_PATH_PATTERNS    (6 + CTRL_X_WANT_IDENT)
  28. #define CTRL_X_PATH_DEFINES    (7 + CTRL_X_WANT_IDENT)
  29. #define CTRL_X_FINISHED        8
  30. #define CTRL_X_DICTIONARY    (9 + CTRL_X_WANT_IDENT)
  31. #define CTRL_X_THESAURUS    (10 + CTRL_X_WANT_IDENT)
  32. #define CTRL_X_CMDLINE        11
  33.  
  34. #define CHECK_KEYS_TIME        30
  35.  
  36. #define CTRL_X_MSG(i) ctrl_x_msgs[(i) & ~CTRL_X_WANT_IDENT]
  37.  
  38. static char *ctrl_x_msgs[] =
  39. {
  40.     N_(" Keyword completion (^N/^P)"), /* ctrl_x_mode == 0, ^P/^N compl. */
  41.     N_(" ^X mode (^E/^Y/^L/^]/^F/^I/^K/^D/^V/^N/^P)"),
  42.     /* Scroll has it's own msgs, in it's place there is the msg for local
  43.      * ctrl_x_mode = 0 (eg continue_status & CONT_LOCAL)  -- Acevedo */
  44.     N_(" Keyword Local completion (^N/^P)"),
  45.     N_(" Whole line completion (^L/^N/^P)"),
  46.     N_(" File name completion (^F/^N/^P)"),
  47.     N_(" Tag completion (^]/^N/^P)"),
  48.     N_(" Path pattern completion (^N/^P)"),
  49.     N_(" Definition completion (^D/^N/^P)"),
  50.     NULL,
  51.     N_(" Dictionary completion (^K/^N/^P)"),
  52.     N_(" Thesaurus completion (^T/^N/^P)"),
  53.     N_(" Command-line completion (^V/^N/^P)")
  54. };
  55.  
  56. static char_u e_hitend[] = N_("Hit end of paragraph");
  57.  
  58. /*
  59.  * Structure used to store one match for insert completion.
  60.  */
  61. struct Completion
  62. {
  63.     struct Completion    *next;
  64.     struct Completion    *prev;
  65.     char_u        *str;      /* matched text */
  66.     char_u        *fname;      /* file containing the match */
  67.     int            original; /* ORIGINAL_TEXT, CONT_S_IPOS or FREE_FNAME */
  68.     int            number;      /* sequence number */
  69. };
  70.  
  71. /* the original text when the expansion begun */
  72. #define ORIGINAL_TEXT    (1)
  73. #define FREE_FNAME    (2)
  74.  
  75. /*
  76.  * All the current matches are stored in a list.
  77.  * "first_match" points to the start of the list.
  78.  * "curr_match" points to the currently selected entry.
  79.  * "shown_match" is different from curr_match during ins_compl_get_exp().
  80.  */
  81. static struct Completion    *first_match = NULL;
  82. static struct Completion    *curr_match = NULL;
  83. static struct Completion    *shown_match = NULL;
  84.  
  85. static int            started_completion = FALSE;
  86. static int            completion_matches = 0;
  87. static char_u            *complete_pat = NULL;
  88. static int            complete_direction = FORWARD;
  89. static int            shown_direction = FORWARD;
  90. static int            completion_pending = FALSE;
  91. static pos_T            initial_pos;
  92. static colnr_T            complete_col = 0;    /* column where the text starts
  93.                            that is being completed */
  94. static int            save_sm;
  95. static char_u            *original_text = NULL;  /* text before completion */
  96. static int            continue_mode = 0;
  97. static expand_T            complete_xp;
  98.  
  99. static int  ins_compl_add __ARGS((char_u *str, int len, char_u *, int dir, int reuse));
  100. static void ins_compl_add_matches __ARGS((int num_matches, char_u **matches, int dir));
  101. static int  ins_compl_make_cyclic __ARGS((void));
  102. static void ins_compl_dictionaries __ARGS((char_u *dict, char_u *pat, int dir, int flags, int thesaurus));
  103. static void ins_compl_free __ARGS((void));
  104. static void ins_compl_clear __ARGS((void));
  105. static void ins_compl_prep __ARGS((int c));
  106. static buf_T *ins_compl_next_buf __ARGS((buf_T *buf, int flag));
  107. static int  ins_compl_get_exp __ARGS((pos_T *ini, int dir));
  108. static void ins_compl_delete __ARGS((void));
  109. static void ins_compl_insert __ARGS((void));
  110. static int  ins_compl_next __ARGS((int allow_get_expansion));
  111. static int  ins_complete __ARGS((int c));
  112. static int  quote_meta __ARGS((char_u *dest, char_u *str, int len));
  113. #endif /* FEAT_INS_EXPAND */
  114.  
  115. #define BACKSPACE_CHAR            1
  116. #define BACKSPACE_WORD            2
  117. #define BACKSPACE_WORD_NOT_SPACE    3
  118. #define BACKSPACE_LINE            4
  119.  
  120. static void ins_redraw __ARGS((void));
  121. static void ins_ctrl_v __ARGS((void));
  122. static void undisplay_dollar __ARGS((void));
  123. static void insert_special __ARGS((int, int, int));
  124. static void redo_literal __ARGS((int c));
  125. static void start_arrow __ARGS((pos_T *end_insert_pos));
  126. static void stop_insert __ARGS((pos_T *end_insert_pos));
  127. static int  echeck_abbr __ARGS((int));
  128. static void replace_push_off __ARGS((int c));
  129. static int  replace_pop __ARGS((void));
  130. static void replace_join __ARGS((int off));
  131. static void replace_pop_ins __ARGS((void));
  132. #ifdef FEAT_MBYTE
  133. static void mb_replace_pop_ins __ARGS((int cc));
  134. #endif
  135. static void replace_flush __ARGS((void));
  136. static void replace_do_bs __ARGS((void));
  137. #ifdef FEAT_CINDENT
  138. static int cindent_on __ARGS((void));
  139. #endif
  140. static void ins_reg __ARGS((void));
  141. static void ins_ctrl_g __ARGS((void));
  142. static int  ins_esc __ARGS((long *count, int cmdchar));
  143. #ifdef FEAT_RIGHTLEFT
  144. static void ins_ctrl_ __ARGS((void));
  145. #endif
  146. #ifdef FEAT_VISUAL
  147. static int ins_start_select __ARGS((int c));
  148. #endif
  149. static void ins_shift __ARGS((int c, int lastc));
  150. static void ins_del __ARGS((void));
  151. static int  ins_bs __ARGS((int c, int mode, int *inserted_space_p));
  152. #ifdef FEAT_MOUSE
  153. static void ins_mouse __ARGS((int c));
  154. static void ins_mousescroll __ARGS((int up));
  155. #endif
  156. static void ins_left __ARGS((void));
  157. static void ins_home __ARGS((int c));
  158. static void ins_end __ARGS((int c));
  159. static void ins_s_left __ARGS((void));
  160. static void ins_right __ARGS((void));
  161. static void ins_s_right __ARGS((void));
  162. static void ins_up __ARGS((int startcol));
  163. static void ins_pageup __ARGS((void));
  164. static void ins_down __ARGS((int startcol));
  165. static void ins_pagedown __ARGS((void));
  166. static int  ins_tab __ARGS((void));
  167. static int  ins_eol __ARGS((int c));
  168. #ifdef FEAT_DIGRAPHS
  169. static int  ins_digraph __ARGS((void));
  170. #endif
  171. static int  ins_copychar __ARGS((linenr_T lnum));
  172. #ifdef FEAT_SMARTINDENT
  173. static void ins_try_si __ARGS((int c));
  174. #endif
  175. static colnr_T get_nolist_virtcol __ARGS((void));
  176.  
  177. static colnr_T    Insstart_textlen;    /* length of line when insert started */
  178. static colnr_T    Insstart_blank_vcol;    /* vcol for first inserted blank */
  179.  
  180. static char_u    *last_insert = NULL;    /* the text of the previous insert,
  181.                        K_SPECIAL and CSI are escaped */
  182. static int    last_insert_skip; /* nr of chars in front of previous insert */
  183. static int    new_insert_skip;  /* nr of chars in front of current insert */
  184.  
  185. #ifdef FEAT_CINDENT
  186. static int    can_cindent;        /* may do cindenting on this line */
  187. #endif
  188.  
  189. static int    old_indent = 0;        /* for ^^D command in insert mode */
  190.  
  191. #ifdef FEAT_RIGHTLEFT
  192. int        revins_on;            /* reverse insert mode on */
  193. int        revins_chars;        /* how much to skip after edit */
  194. int        revins_legal;        /* was the last char 'legal'? */
  195. int        revins_scol;        /* start column of revins session */
  196. #endif
  197.  
  198. #if defined(FEAT_MBYTE) && defined(MACOS)
  199. static short    previous_script = smRoman;
  200. #endif
  201.  
  202. static int    ins_need_undo;        /* call u_save() before inserting a
  203.                        char.  Set when edit() is called.
  204.                        after that arrow_used is used. */
  205.  
  206. /*
  207.  * edit(): Start inserting text.
  208.  *
  209.  * "cmdchar" can be:
  210.  * 'i'    normal insert command
  211.  * 'a'    normal append command
  212.  * 'R'    replace command
  213.  * 'r'    "r<CR>" command: insert one <CR>.  Note: count can be > 1, for redo,
  214.  *    but still only one <CR> is inserted.  The <Esc> is not used for redo.
  215.  * 'g'    "gI" command.
  216.  * 'V'    "gR" command for Virtual Replace mode.
  217.  * 'v'    "gr" command for single character Virtual Replace mode.
  218.  *
  219.  * This function is not called recursively.  For CTRL-O commands, it returns
  220.  * and lets the caller handle the Normal-mode command.
  221.  *
  222.  * Return TRUE if a CTRL-O command caused the return (insert mode pending).
  223.  */
  224.     int
  225. edit(cmdchar, startln, count)
  226.     int        cmdchar;
  227.     int        startln;    /* if set, insert at start of line */
  228.     long    count;
  229. {
  230.     int        c = 0;
  231.     char_u    *ptr;
  232.     int        lastc;
  233.     colnr_T    mincol;
  234.     static linenr_T o_lnum = 0;
  235.     static int    o_eol = FALSE;
  236.     int        i;
  237.     int        did_backspace = TRUE;        /* previous char was backspace */
  238. #ifdef FEAT_CINDENT
  239.     int        line_is_white = FALSE;        /* line is empty before insert */
  240. #endif
  241.     linenr_T    old_topline = 0;        /* topline before insertion */
  242. #ifdef FEAT_DIFF
  243.     int        old_topfill = -1;
  244. #endif
  245.     int        inserted_space = FALSE;     /* just inserted a space */
  246.     int        replaceState = REPLACE;
  247.     int        did_restart_edit = restart_edit;
  248.  
  249.     /* sleep before redrawing, needed for "CTRL-O :" that results in an
  250.      * error message */
  251.     check_for_delay(TRUE);
  252.  
  253. #ifdef HAVE_SANDBOX
  254.     /* Don't allow inserting in the sandbox. */
  255.     if (sandbox != 0)
  256.     {
  257.     EMSG(_(e_sandbox));
  258.     return FALSE;
  259.     }
  260. #endif
  261.  
  262. #ifdef FEAT_INS_EXPAND
  263.     ins_compl_clear();        /* clear stuff for CTRL-X mode */
  264. #endif
  265.  
  266. #ifdef FEAT_MOUSE
  267.     /*
  268.      * When doing a paste with the middle mouse button, Insstart is set to
  269.      * where the paste started.
  270.      */
  271.     if (where_paste_started.lnum != 0)
  272.     Insstart = where_paste_started;
  273.     else
  274. #endif
  275.     {
  276.     Insstart = curwin->w_cursor;
  277.     if (startln)
  278.         Insstart.col = 0;
  279.     }
  280.     Insstart_textlen = linetabsize(ml_get_curline());
  281.     Insstart_blank_vcol = MAXCOL;
  282.     if (!did_ai)
  283.     ai_col = 0;
  284.  
  285.     if (cmdchar != NUL && restart_edit == 0)
  286.     {
  287.     ResetRedobuff();
  288.     AppendNumberToRedobuff(count);
  289. #ifdef FEAT_VREPLACE
  290.     if (cmdchar == 'V' || cmdchar == 'v')
  291.     {
  292.         /* "gR" or "gr" command */
  293.         AppendCharToRedobuff('g');
  294.         AppendCharToRedobuff((cmdchar == 'v') ? 'r' : 'R');
  295.     }
  296.     else
  297. #endif
  298.     {
  299.         AppendCharToRedobuff(cmdchar);
  300.         if (cmdchar == 'g')            /* "gI" command */
  301.         AppendCharToRedobuff('I');
  302.         else if (cmdchar == 'r')        /* "r<CR>" command */
  303.         count = 1;            /* insert only one <CR> */
  304.     }
  305.     }
  306.  
  307.     if (cmdchar == 'R')
  308.     {
  309. #ifdef FEAT_FKMAP
  310.     if (p_fkmap && p_ri)
  311.     {
  312.         beep_flush();
  313.         EMSG(farsi_text_3);        /* encoded in Farsi */
  314.         State = INSERT;
  315.     }
  316.     else
  317. #endif
  318.     State = REPLACE;
  319.     }
  320. #ifdef FEAT_VREPLACE
  321.     else if (cmdchar == 'V' || cmdchar == 'v')
  322.     {
  323.     State = VREPLACE;
  324.     replaceState = VREPLACE;
  325.     orig_line_count = curbuf->b_ml.ml_line_count;
  326.     vr_lines_changed = 1;
  327.     }
  328. #endif
  329.     else
  330.     State = INSERT;
  331.  
  332.     if (curbuf->b_p_iminsert == B_IMODE_LMAP)
  333.     State |= LANGMAP;
  334. #ifdef USE_IM_CONTROL
  335.     im_set_active(curbuf->b_p_iminsert == B_IMODE_IM);
  336. #endif
  337.  
  338. #if defined(FEAT_MBYTE) && defined(MACOS)
  339.     KeyScript(previous_script);
  340. #endif
  341.  
  342.     /*
  343.      * Need to recompute the cursor position, it might move when the cursor is
  344.      * on a TAB or special character.
  345.      */
  346.     curs_columns(TRUE);
  347.  
  348. #ifdef FEAT_MOUSE
  349.     setmouse();
  350. #endif
  351. #ifdef FEAT_CMDL_INFO
  352.     clear_showcmd();
  353. #endif
  354. #ifdef FEAT_RIGHTLEFT
  355.     /* there is no reverse replace mode */
  356.     revins_on = (State == INSERT && p_ri);
  357.     if (revins_on)
  358.     undisplay_dollar();
  359.     revins_chars = 0;
  360.     revins_legal = 0;
  361.     revins_scol = -1;
  362. #endif
  363.  
  364.     /*
  365.      * Handle restarting Insert mode.
  366.      * Don't do this for "CTRL-O ." (repeat an insert): we get here with
  367.      * restart_edit non-zero, and something in the stuff buffer.
  368.      */
  369.     if (restart_edit != 0 && stuff_empty())
  370.     {
  371. #ifdef FEAT_MOUSE
  372.     /*
  373.      * After a paste we consider text typed to be part of the insert for
  374.      * the pasted text. You can backspace over the pasted text too.
  375.      */
  376.     if (where_paste_started.lnum)
  377.         arrow_used = FALSE;
  378.     else
  379. #endif
  380.         arrow_used = TRUE;
  381.     restart_edit = 0;
  382.  
  383.     /*
  384.      * If the cursor was after the end-of-line before the CTRL-O and it is
  385.      * now at the end-of-line, put it after the end-of-line (this is not
  386.      * correct in very rare cases).
  387.      * Also do this if curswant is greater than the current virtual
  388.      * column.  Eg after "^O$" or "^O80|".
  389.      */
  390.     validate_virtcol();
  391.     update_curswant();
  392.     if (((o_eol && curwin->w_cursor.lnum == o_lnum)
  393.             || curwin->w_curswant > curwin->w_virtcol)
  394.         && *(ptr = ml_get_curline() + curwin->w_cursor.col) != NUL)
  395.     {
  396.         if (ptr[1] == NUL)
  397.         ++curwin->w_cursor.col;
  398. #ifdef FEAT_MBYTE
  399.         else if (has_mbyte)
  400.         {
  401.         i = (*mb_ptr2len_check)(ptr);
  402.         if (ptr[i] == NUL)
  403.             curwin->w_cursor.col += i;
  404.         }
  405. #endif
  406.     }
  407.     }
  408.     else
  409.     {
  410.     arrow_used = FALSE;
  411.     o_eol = FALSE;
  412.     }
  413.  
  414.     /* Need to save the line for undo before inserting the first char. */
  415.     ins_need_undo = TRUE;
  416.  
  417. #ifdef FEAT_MOUSE
  418.     where_paste_started.lnum = 0;
  419. #endif
  420. #ifdef FEAT_CINDENT
  421.     can_cindent = TRUE;
  422. #endif
  423. #ifdef FEAT_FOLDING
  424.     /* The cursor line is not in a closed fold, unless 'insertmode' is set or
  425.      * restarting. */
  426.     if (!p_im && did_restart_edit == 0)
  427.     foldOpenCursor();
  428. #endif
  429.  
  430.     /*
  431.      * If 'showmode' is set, show the current (insert/replace/..) mode.
  432.      * A warning message for changing a readonly file is given here, before
  433.      * actually changing anything.  It's put after the mode, if any.
  434.      */
  435.     i = 0;
  436.     if (p_smd)
  437.     i = showmode();
  438.  
  439.     if (!p_im && did_restart_edit == 0)
  440.     change_warning(i + 1);
  441.  
  442. #ifdef CURSOR_SHAPE
  443.     ui_cursor_shape();        /* may show different cursor shape */
  444. #endif
  445. #ifdef FEAT_DIGRAPHS
  446.     do_digraph(-1);        /* clear digraphs */
  447. #endif
  448.  
  449. /*
  450.  * Get the current length of the redo buffer, those characters have to be
  451.  * skipped if we want to get to the inserted characters.
  452.  */
  453.     ptr = get_inserted();
  454.     if (ptr == NULL)
  455.     new_insert_skip = 0;
  456.     else
  457.     {
  458.     new_insert_skip = (int)STRLEN(ptr);
  459.     vim_free(ptr);
  460.     }
  461.  
  462.     old_indent = 0;
  463.  
  464.     /*
  465.      * Main loop in Insert mode: repeat until Insert mode is left.
  466.      */
  467.     for (;;)
  468.     {
  469. #ifdef FEAT_RIGHTLEFT
  470.     if (!revins_legal)
  471.         revins_scol = -1;        /* reset on illegal motions */
  472.     else
  473.         revins_legal = 0;
  474. #endif
  475.     if (arrow_used)        /* don't repeat insert when arrow key used */
  476.         count = 0;
  477.  
  478.     /* set curwin->w_curswant for next K_DOWN or K_UP */
  479.     if (!arrow_used)
  480.         curwin->w_set_curswant = TRUE;
  481.  
  482.     /*
  483.      * When emsg() was called msg_scroll will have been set.
  484.      */
  485.     msg_scroll = FALSE;
  486.  
  487. #ifdef FEAT_FOLDING
  488.     /* Open fold at the cursor line, according to 'foldopen'. */
  489.     if (fdo_flags & FDO_INSERT)
  490.         foldOpenCursor();
  491.     /* Close folds where the cursor isn't, according to 'foldclose' */
  492.     if (!char_avail())
  493.         foldCheckClose();
  494. #endif
  495.  
  496.     /*
  497.      * If we inserted a character at the last position of the last line in
  498.      * the window, scroll the window one line up. This avoids an extra
  499.      * redraw.
  500.      * This is detected when the cursor column is smaller after inserting
  501.      * something.
  502.      * Don't do this when the topline changed already, it has
  503.      * already been adjusted (by insertchar() calling open_line())).
  504.      */
  505.     if (curbuf->b_mod_set
  506.         && curwin->w_p_wrap
  507.         && !did_backspace
  508.         && curwin->w_topline == old_topline
  509. #ifdef FEAT_DIFF
  510.         && curwin->w_topfill == old_topfill
  511. #endif
  512.         )
  513.     {
  514.         mincol = curwin->w_wcol;
  515.         validate_cursor_col();
  516.  
  517.         if ((int)curwin->w_wcol < (int)mincol - curbuf->b_p_ts
  518.             && curwin->w_wrow == W_WINROW(curwin)
  519.                          + curwin->w_height - 1 - p_so
  520.             && (curwin->w_cursor.lnum != curwin->w_topline
  521. #ifdef FEAT_DIFF
  522.             || curwin->w_topfill > 0
  523. #endif
  524.             ))
  525.         {
  526. #ifdef FEAT_DIFF
  527.         if (curwin->w_topfill > 0)
  528.             --curwin->w_topfill;
  529.         else
  530. #endif
  531. #ifdef FEAT_FOLDING
  532.         if (hasFolding(curwin->w_topline, NULL, &old_topline))
  533.             set_topline(curwin, old_topline + 1);
  534.         else
  535. #endif
  536.             set_topline(curwin, curwin->w_topline + 1);
  537.         }
  538.     }
  539.  
  540.     /* May need to adjust w_topline to show the cursor. */
  541.     update_topline();
  542.  
  543.     did_backspace = FALSE;
  544.  
  545.     validate_cursor();        /* may set must_redraw */
  546.  
  547.     /*
  548.      * Redraw the display when no characters are waiting.
  549.      * Also shows mode, ruler and positions cursor.
  550.      */
  551.     ins_redraw();
  552.  
  553. #ifdef FEAT_SCROLLBIND
  554.     if (curwin->w_p_scb)
  555.         do_check_scrollbind(TRUE);
  556. #endif
  557.  
  558.     update_curswant();
  559.     old_topline = curwin->w_topline;
  560. #ifdef FEAT_DIFF
  561.     old_topfill = curwin->w_topfill;
  562. #endif
  563.  
  564. #ifdef USE_ON_FLY_SCROLL
  565.     dont_scroll = FALSE;        /* allow scrolling here */
  566. #endif
  567.  
  568.     /*
  569.      * Get a character for Insert mode.
  570.      */
  571.     lastc = c;            /* remember previous char for CTRL-D */
  572.     c = safe_vgetc();
  573.  
  574. #ifdef FEAT_RIGHTLEFT
  575.     if (p_hkmap && KeyTyped)
  576.         c = hkmap(c);        /* Hebrew mode mapping */
  577. #endif
  578. #ifdef FEAT_FKMAP
  579.     if (p_fkmap && KeyTyped)
  580.         c = fkmap(c);        /* Farsi mode mapping */
  581. #endif
  582.  
  583. #ifdef FEAT_INS_EXPAND
  584.     /* Prepare for or stop CTRL-X mode.  This doesn't do completion, but
  585.      * it does fix up the text when finishing completion. */
  586.     ins_compl_prep(c);
  587. #endif
  588.  
  589.     /* CTRL-\ CTRL-N goes to Normal mode */
  590.     if (c == Ctrl_BSL)
  591.     {
  592.         /* may need to redraw when no more chars available now */
  593.         ins_redraw();
  594.         ++no_mapping;
  595.         ++allow_keys;
  596.         c = safe_vgetc();
  597.         --no_mapping;
  598.         --allow_keys;
  599.         if (c != Ctrl_N)        /* it's something else */
  600.         {
  601.         vungetc(c);
  602.         c = Ctrl_BSL;
  603.         }
  604.         else
  605.         {
  606.         count = 0;
  607.         goto doESCkey;
  608.         }
  609.     }
  610.  
  611. #ifdef FEAT_DIGRAPHS
  612.     c = do_digraph(c);
  613. #endif
  614.  
  615. #ifdef FEAT_INS_EXPAND
  616.     if (c == Ctrl_V && ctrl_x_mode == CTRL_X_CMDLINE)
  617.         goto docomplete;
  618. #endif
  619.     if (c == Ctrl_V || c == Ctrl_Q)
  620.     {
  621.         ins_ctrl_v();
  622.         c = Ctrl_V;    /* pretend CTRL-V is last typed character */
  623.         continue;
  624.     }
  625.  
  626. #ifdef FEAT_CINDENT
  627.     if (cindent_on()
  628. # ifdef FEAT_INS_EXPAND
  629.         && ctrl_x_mode == 0
  630. # endif
  631.        )
  632.     {
  633.         /* A key name preceded by a bang means this key is not to be
  634.          * inserted.  Skip ahead to the re-indenting below.
  635.          * A key name preceded by a star means that indenting has to be
  636.          * done before inserting the key. */
  637.         line_is_white = inindent(0);
  638.         if (in_cinkeys(c, '!', line_is_white))
  639.         goto force_cindent;
  640.         if (can_cindent && in_cinkeys(c, '*', line_is_white)
  641.                             && stop_arrow() == OK)
  642.         do_c_expr_indent();
  643.     }
  644. #endif
  645.  
  646. #ifdef FEAT_RIGHTLEFT
  647.     if (curwin->w_p_rl)
  648.         switch (c)
  649.         {
  650.         case K_LEFT:    c = K_RIGHT; break;
  651.         case K_S_LEFT:    c = K_S_RIGHT; break;
  652.         case K_C_LEFT:    c = K_C_RIGHT; break;
  653.         case K_RIGHT:    c = K_LEFT; break;
  654.         case K_S_RIGHT: c = K_S_LEFT; break;
  655.         case K_C_RIGHT: c = K_C_LEFT; break;
  656.         }
  657. #endif
  658.  
  659. #ifdef FEAT_VISUAL
  660.     /*
  661.      * If 'keymodel' contains "startsel", may start selection.  If it
  662.      * does, a CTRL-O and c will be stuffed, we need to get these
  663.      * characters.
  664.      */
  665.     if (ins_start_select(c))
  666.         continue;
  667. #endif
  668.  
  669.     /*
  670.      * The big switch to handle a character in insert mode.
  671.      */
  672.     switch (c)
  673.     {
  674.     /* toggle insert/replace mode */
  675.     case K_INS:
  676.     case K_KINS:
  677. #ifdef FEAT_FKMAP
  678.         if (p_fkmap && p_ri)
  679.         {
  680.         beep_flush();
  681.         EMSG(farsi_text_3);    /* encoded in Farsi */
  682.         break;
  683.         }
  684. #endif
  685.         if (State & REPLACE_FLAG)
  686.         State = INSERT | (State & LANGMAP);
  687.         else
  688.         State = replaceState | (State & LANGMAP);
  689.         AppendCharToRedobuff(K_INS);
  690.         showmode();
  691. #ifdef CURSOR_SHAPE
  692.         ui_cursor_shape();        /* may show different cursor shape */
  693. #endif
  694.         break;
  695.  
  696. #ifdef FEAT_INS_EXPAND
  697.     /* Enter CTRL-X mode */
  698.     case Ctrl_X:
  699.         /* CTRL-X after CTRL-V CTRL-X doesn't do anything, so that CTRL-X
  700.          * CTRL-V works like CTRL-N */
  701.         if (ctrl_x_mode != CTRL_X_CMDLINE)
  702.         {
  703.         /* if the next ^X<> won't ADD nothing, then reset
  704.          * continue_status */
  705.         if (continue_status & CONT_N_ADDS)
  706.             continue_status = (continue_status | CONT_INTRPT);
  707.         else
  708.             continue_status = 0;
  709.         /* We're not sure which CTRL-X mode it will be yet */
  710.         ctrl_x_mode = CTRL_X_NOT_DEFINED_YET;
  711.         edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode));
  712.         edit_submode_pre = NULL;
  713.         showmode();
  714.         }
  715.         break;
  716. #endif
  717.  
  718.     /* end of Select mode mapping - ignore */
  719.     case K_SELECT:
  720.         break;
  721.  
  722.     /* suspend when 'insertmode' set */
  723.     case Ctrl_Z:
  724.         if (!p_im)
  725.         goto normalchar;    /* insert CTRL-Z as normal char */
  726.         stuffReadbuff((char_u *)":st\r");
  727.         c = Ctrl_O;
  728.         /*FALLTHROUGH*/
  729.  
  730.     /* execute one command */
  731.     case Ctrl_O:
  732.         if (echeck_abbr(Ctrl_O + ABBR_OFF))
  733.         break;
  734.         count = 0;
  735. #ifdef FEAT_VREPLACE
  736.         if (State & VREPLACE_FLAG)
  737.         restart_edit = 'V';
  738.         else
  739. #endif
  740.         if (State & REPLACE_FLAG)
  741.         restart_edit = 'R';
  742.         else
  743.         restart_edit = 'I';
  744.         o_lnum = curwin->w_cursor.lnum;
  745.         o_eol = (gchar_cursor() == NUL);
  746.         goto doESCkey;
  747.  
  748. #ifdef FEAT_SNIFF
  749.     case K_SNIFF:
  750.         stuffcharReadbuff(K_SNIFF);
  751.         goto doESCkey;
  752. #endif
  753.  
  754.     /* Hitting the help key in insert mode is like <ESC> <Help> */
  755.     case K_HELP:
  756.     case K_F1:
  757.     case K_XF1:
  758.         stuffcharReadbuff(K_HELP);
  759.         if (p_im)
  760.         need_start_insertmode = TRUE;
  761.         goto doESCkey;
  762.  
  763.     /* an escape ends input mode */
  764.     case ESC:
  765.         if (echeck_abbr(ESC + ABBR_OFF))
  766.         break;
  767.         /*FALLTHROUGH*/
  768.  
  769.     case Ctrl_C:
  770. #ifdef FEAT_CMDWIN
  771.         if (c == Ctrl_C && cmdwin_type != 0)
  772.         {
  773.         /* Close the cmdline window. */
  774.         cmdwin_result = K_IGNORE;
  775.         goto doESCkey;
  776.         }
  777. #endif
  778.  
  779. #ifdef UNIX
  780. do_intr:
  781. #endif
  782.         /* when 'insertmode' set, and not halfway a mapping, don't leave
  783.          * Insert mode */
  784.         if (goto_im())
  785.         {
  786.         if (got_int)
  787.         {
  788.             (void)vgetc();        /* flush all buffers */
  789.             got_int = FALSE;
  790.         }
  791.         else
  792.             vim_beep();
  793.         break;
  794.         }
  795. doESCkey:
  796.         /*
  797.          * This is the ONLY return from edit()!
  798.          */
  799.         if (ins_esc(&count, cmdchar))
  800.         return (c == Ctrl_O);
  801.         continue;
  802.  
  803.     /*
  804.      * Insert the previously inserted text.
  805.      * For ^@ the trailing ESC will end the insert, unless there is an
  806.      * error.
  807.      */
  808.     case K_ZERO:
  809.     case NUL:
  810.     case Ctrl_A:
  811.         if (stuff_inserted(NUL, 1L, (c == Ctrl_A)) == FAIL
  812.                            && c != Ctrl_A && !p_im)
  813.         goto doESCkey;        /* quit insert mode */
  814.         inserted_space = FALSE;
  815.         break;
  816.  
  817.     /* insert the contents of a register */
  818.     case Ctrl_R:
  819.         ins_reg();
  820.         inserted_space = FALSE;
  821.         break;
  822.  
  823.     case Ctrl_G:
  824.         ins_ctrl_g();
  825.         break;
  826.  
  827.     case Ctrl_HAT:
  828.         if (map_to_exists_mode((char_u *)"", LANGMAP))
  829.         {
  830.         /* ":lmap" mappings exists, Toggle use of ":lmap" mappings. */
  831.         if (curbuf->b_p_iminsert == B_IMODE_LMAP)
  832.         {
  833.             curbuf->b_p_iminsert = B_IMODE_NONE;
  834.             State &= ~LANGMAP;
  835.         }
  836.         else
  837.         {
  838.             curbuf->b_p_iminsert = B_IMODE_LMAP;
  839.             State |= LANGMAP;
  840. #ifdef USE_IM_CONTROL
  841.             im_set_active(FALSE);
  842. #endif
  843.         }
  844.         }
  845. #ifdef USE_IM_CONTROL
  846.         else
  847.         {
  848.         /* There are no ":lmap" mappings, toggle IM */
  849.         if (curbuf->b_p_iminsert == B_IMODE_IM)
  850.         {
  851.             curbuf->b_p_iminsert = B_IMODE_NONE;
  852.             im_set_active(FALSE);
  853.         }
  854.         else
  855.         {
  856.             curbuf->b_p_iminsert = B_IMODE_IM;
  857.             State &= ~LANGMAP;
  858.             im_set_active(TRUE);
  859.         }
  860.         }
  861. #endif
  862.         set_iminsert_global();
  863.         showmode();
  864. #if defined(FEAT_WINDOWS) && defined(FEAT_KEYMAP)
  865.         /* Show/unshow value of 'keymap' in status lines. */
  866.         status_redraw_curbuf();
  867. #endif
  868.         break;
  869.  
  870. #ifdef FEAT_RIGHTLEFT
  871.     case Ctrl__:
  872.         if (!p_ari)
  873.         goto normalchar;
  874.         ins_ctrl_();
  875.         break;
  876. #endif
  877.  
  878.     /* Make indent one shiftwidth smaller. */
  879.     case Ctrl_D:
  880. #if defined(FEAT_INS_EXPAND) && defined(FEAT_FIND_ID)
  881.         if (ctrl_x_mode == CTRL_X_PATH_DEFINES)
  882.         goto docomplete;
  883. #endif
  884.         /* FALLTHROUGH */
  885.  
  886.     /* Make indent one shiftwidth greater. */
  887.     case Ctrl_T:
  888. # ifdef FEAT_INS_EXPAND
  889.         if (c == Ctrl_T && ctrl_x_mode == CTRL_X_THESAURUS)
  890.         {
  891.         if (*curbuf->b_p_tsr == NUL && *p_tsr == NUL)
  892.         {
  893.             ctrl_x_mode = 0;
  894.             msg_attr((char_u *)_("'thesaurus' option is empty"),
  895.                  hl_attr(HLF_E));
  896.             if (emsg_silent == 0)
  897.             {
  898.             vim_beep();
  899.             setcursor();
  900.             out_flush();
  901.             ui_delay(2000L, FALSE);
  902.             }
  903.             break;
  904.         }
  905.         goto docomplete;
  906.         }
  907. # endif
  908.         ins_shift(c, lastc);
  909.         inserted_space = FALSE;
  910.         break;
  911.  
  912.     /* delete character under the cursor */
  913.     case K_DEL:
  914.     case K_KDEL:
  915.         ins_del();
  916.         break;
  917.  
  918.     /* delete character before the cursor */
  919.     case K_BS:
  920.     case Ctrl_H:
  921.         did_backspace = ins_bs(c, BACKSPACE_CHAR, &inserted_space);
  922.         break;
  923.  
  924.     /* delete word before the cursor */
  925.     case Ctrl_W:
  926.         did_backspace = ins_bs(c, BACKSPACE_WORD, &inserted_space);
  927.         break;
  928.  
  929.     /* delete all inserted text in current line */
  930.     case Ctrl_U:
  931.         did_backspace = ins_bs(c, BACKSPACE_LINE, &inserted_space);
  932.         inserted_space = FALSE;
  933.         break;
  934.  
  935. #ifdef FEAT_MOUSE
  936.     case K_LEFTMOUSE:
  937.     case K_LEFTMOUSE_NM:
  938.     case K_LEFTDRAG:
  939.     case K_LEFTRELEASE:
  940.     case K_LEFTRELEASE_NM:
  941.     case K_MIDDLEMOUSE:
  942.     case K_MIDDLEDRAG:
  943.     case K_MIDDLERELEASE:
  944.     case K_RIGHTMOUSE:
  945.     case K_RIGHTDRAG:
  946.     case K_RIGHTRELEASE:
  947.         ins_mouse(c);
  948.         break;
  949.  
  950.     /* Default action for scroll wheel up: scroll up */
  951.     case K_MOUSEDOWN:
  952.         ins_mousescroll(FALSE);
  953.         break;
  954.  
  955.     /* Default action for scroll wheel down: scroll down */
  956.     case K_MOUSEUP:
  957.         ins_mousescroll(TRUE);
  958.         break;
  959. #endif
  960.  
  961.     case K_IGNORE:
  962.         break;
  963.  
  964. #ifdef FEAT_GUI
  965.     case K_VER_SCROLLBAR:
  966.         ins_scroll();
  967.         break;
  968.  
  969.     case K_HOR_SCROLLBAR:
  970.         ins_horscroll();
  971.         break;
  972. #endif
  973.  
  974.     case K_HOME:
  975.     case K_KHOME:
  976.     case K_XHOME:
  977.     case K_S_HOME:
  978.     case K_C_HOME:
  979.         ins_home(c);
  980.         break;
  981.  
  982.     case K_END:
  983.     case K_KEND:
  984.     case K_XEND:
  985.     case K_S_END:
  986.     case K_C_END:
  987.         ins_end(c);
  988.         break;
  989.  
  990.     case K_LEFT:
  991.         ins_left();
  992.         break;
  993.  
  994.     case K_S_LEFT:
  995.     case K_C_LEFT:
  996.         ins_s_left();
  997.         break;
  998.  
  999.     case K_RIGHT:
  1000.         ins_right();
  1001.         break;
  1002.  
  1003.     case K_S_RIGHT:
  1004.     case K_C_RIGHT:
  1005.         ins_s_right();
  1006.         break;
  1007.  
  1008.     case K_UP:
  1009.         ins_up(FALSE);
  1010.         break;
  1011.  
  1012.     case K_S_UP:
  1013.     case K_PAGEUP:
  1014.     case K_KPAGEUP:
  1015.         ins_pageup();
  1016.         break;
  1017.  
  1018.     case K_DOWN:
  1019.         ins_down(FALSE);
  1020.         break;
  1021.  
  1022.     case K_S_DOWN:
  1023.     case K_PAGEDOWN:
  1024.     case K_KPAGEDOWN:
  1025.         ins_pagedown();
  1026.         break;
  1027.  
  1028.     /* When <S-Tab> isn't mapped, use it like a normal TAB */
  1029.     case K_S_TAB:
  1030.         c = TAB;
  1031.         /* FALLTHROUGH */
  1032.  
  1033.     /* TAB or Complete patterns along path */
  1034.     case TAB:
  1035. #if defined(FEAT_INS_EXPAND) && defined(FEAT_FIND_ID)
  1036.         if (ctrl_x_mode == CTRL_X_PATH_PATTERNS)
  1037.         goto docomplete;
  1038. #endif
  1039.         inserted_space = FALSE;
  1040.         if (ins_tab())
  1041.         goto normalchar;    /* insert TAB as a normal char */
  1042.         break;
  1043.  
  1044.     case K_KENTER:
  1045.         c = CR;
  1046.         /* FALLTHROUGH */
  1047.     case CR:
  1048.     case NL:
  1049. #ifdef FEAT_CMDWIN
  1050.         if (cmdwin_type != 0)
  1051.         {
  1052.         /* Execute the command in the cmdline window. */
  1053.         cmdwin_result = CR;
  1054.         goto doESCkey;
  1055.         }
  1056. #endif
  1057.         if (ins_eol(c) && !p_im)
  1058.         goto doESCkey;        /* out of memory */
  1059.         inserted_space = FALSE;
  1060.         break;
  1061.  
  1062. #if defined(FEAT_DIGRAPHS) || defined (FEAT_INS_EXPAND)
  1063.     case Ctrl_K:
  1064. # ifdef FEAT_INS_EXPAND
  1065.         if (ctrl_x_mode == CTRL_X_DICTIONARY)
  1066.         {
  1067.         if (*curbuf->b_p_dict == NUL && *p_dict == NUL)
  1068.         {
  1069.             ctrl_x_mode = 0;
  1070.             msg_attr((char_u *)_("'dictionary' option is empty"),
  1071.                  hl_attr(HLF_E));
  1072.             if (emsg_silent == 0)
  1073.             {
  1074.             vim_beep();
  1075.             setcursor();
  1076.             out_flush();
  1077.             ui_delay(2000L, FALSE);
  1078.             }
  1079.             break;
  1080.         }
  1081.         goto docomplete;
  1082.         }
  1083. # endif
  1084. # ifdef FEAT_DIGRAPHS
  1085.         c = ins_digraph();
  1086.         if (c == NUL)
  1087.         break;
  1088. # endif
  1089.         goto normalchar;
  1090. #endif /* FEAT_DIGRAPHS || FEAT_INS_EXPAND */
  1091.  
  1092. #ifdef FEAT_INS_EXPAND
  1093.     case Ctrl_RSB:        /* Tag name completion after ^X */
  1094.         if (ctrl_x_mode != CTRL_X_TAGS)
  1095.         goto normalchar;
  1096.         goto docomplete;
  1097.  
  1098.     case Ctrl_F:        /* File name completion after ^X */
  1099.         if (ctrl_x_mode != CTRL_X_FILES)
  1100.         goto normalchar;
  1101.         goto docomplete;
  1102. #endif
  1103.  
  1104.     case Ctrl_L:        /* Whole line completion after ^X */
  1105. #ifdef FEAT_INS_EXPAND
  1106.         if (ctrl_x_mode != CTRL_X_WHOLE_LINE)
  1107. #endif
  1108.         {
  1109.         /* CTRL-L with 'insertmode' set: Leave Insert mode */
  1110.         if (p_im)
  1111.         {
  1112.             if (echeck_abbr(Ctrl_L + ABBR_OFF))
  1113.             break;
  1114.             goto doESCkey;
  1115.         }
  1116.         goto normalchar;
  1117.         }
  1118. #ifdef FEAT_INS_EXPAND
  1119.         /* FALLTHROUGH */
  1120.  
  1121.     /* Do previous/next pattern completion */
  1122.     case Ctrl_P:
  1123.     case Ctrl_N:
  1124.         /* if 'complete' is empty then plain ^P is no longer special,
  1125.          * but it is under other ^X modes */
  1126.         if (*curbuf->b_p_cpt == NUL
  1127.             && ctrl_x_mode != 0
  1128.             && !(continue_status & CONT_LOCAL))
  1129.         goto normalchar;
  1130.  
  1131. docomplete:
  1132.         if (ins_complete(c) == FAIL)
  1133.         continue_status = 0;
  1134.         break;
  1135. #endif /* FEAT_INS_EXPAND */
  1136.  
  1137.     case Ctrl_Y:        /* copy from previous line or scroll down */
  1138.     case Ctrl_E:        /* copy from next line       or scroll up */
  1139. #ifdef FEAT_INS_EXPAND
  1140.         if (ctrl_x_mode == CTRL_X_SCROLL)
  1141.         {
  1142.         if (c == Ctrl_Y)
  1143.             scrolldown_clamp();
  1144.         else
  1145.             scrollup_clamp();
  1146.         redraw_later(VALID);
  1147.         }
  1148.         else
  1149. #endif
  1150.         {
  1151.         c = ins_copychar(curwin->w_cursor.lnum
  1152.                          + (c == Ctrl_Y ? -1 : 1));
  1153.         if (c != NUL)
  1154.         {
  1155.             long    tw_save;
  1156.  
  1157.             /* The character must be taken literally, insert like it
  1158.              * was typed after a CTRL-V, and pretend 'textwidth'
  1159.              * wasn't set.  Digits, 'o' and 'x' are special after a
  1160.              * CTRL-V, don't use it for these. */
  1161.             if (c < 256 && !isalnum(c))
  1162.             AppendToRedobuff((char_u *)CTRL_V_STR);    /* CTRL-V */
  1163.             tw_save = curbuf->b_p_tw;
  1164.             curbuf->b_p_tw = -1;
  1165.             insert_special(c, TRUE, FALSE);
  1166.             curbuf->b_p_tw = tw_save;
  1167. #ifdef FEAT_RIGHTLEFT
  1168.             revins_chars++;
  1169.             revins_legal++;
  1170. #endif
  1171.             c = Ctrl_V;    /* pretend CTRL-V is last character */
  1172.         }
  1173.         }
  1174.         break;
  1175.  
  1176.       default:
  1177. #ifdef UNIX
  1178.         if (c == intr_char)        /* special interrupt char */
  1179.         goto do_intr;
  1180. #endif
  1181.  
  1182.         /*
  1183.          * Insert a nomal character.
  1184.          */
  1185. normalchar:
  1186. #ifdef FEAT_SMARTINDENT
  1187.         /* Try to perform smart-indenting. */
  1188.         ins_try_si(c);
  1189. #endif
  1190.  
  1191.         if (c == ' ')
  1192.         {
  1193.         inserted_space = TRUE;
  1194. #ifdef FEAT_CINDENT
  1195.         if (inindent(0))
  1196.             can_cindent = FALSE;
  1197. #endif
  1198.         if (Insstart_blank_vcol == MAXCOL
  1199.             && curwin->w_cursor.lnum == Insstart.lnum)
  1200.             Insstart_blank_vcol = get_nolist_virtcol();
  1201.         }
  1202.  
  1203.         if (vim_iswordc(c) || !echeck_abbr(c))
  1204.         {
  1205.         insert_special(c, FALSE, FALSE);
  1206. #ifdef FEAT_RIGHTLEFT
  1207.         revins_legal++;
  1208.         revins_chars++;
  1209. #endif
  1210.         }
  1211. #ifdef FEAT_FOLDING
  1212.         /* When inserting a character the cursor line must never be in a
  1213.          * closed fold. */
  1214.         foldOpenCursor();
  1215. #endif
  1216.         break;
  1217.     }   /* end of switch (c) */
  1218.  
  1219.     /* If the cursor was moved we didn't just insert a space */
  1220.     if (arrow_used)
  1221.         inserted_space = FALSE;
  1222.  
  1223. #ifdef FEAT_CINDENT
  1224.     if (can_cindent && cindent_on()
  1225. # ifdef FEAT_INS_EXPAND
  1226.         && ctrl_x_mode == 0
  1227. # endif
  1228.        )
  1229.     {
  1230. force_cindent:
  1231.         /*
  1232.          * Indent now if a key was typed that is in 'cinkeys'.
  1233.          */
  1234.         if (in_cinkeys(c, ' ', line_is_white))
  1235.         {
  1236.         if (stop_arrow() == OK)
  1237.             /* re-indent the current line */
  1238.             do_c_expr_indent();
  1239.         }
  1240.     }
  1241. #endif /* FEAT_CINDENT */
  1242.  
  1243.     }    /* for (;;) */
  1244.     /* NOTREACHED */
  1245. }
  1246.  
  1247. /*
  1248.  * Redraw for Insert mode.
  1249.  * This is postponed until getting the next character to make '$' in the 'cpo'
  1250.  * option work correctly.
  1251.  * Only redraw when there are no characters available.  This speeds up
  1252.  * inserting sequences of characters (e.g., for CTRL-R).
  1253.  */
  1254.     static void
  1255. ins_redraw()
  1256. {
  1257.     if (!char_avail())
  1258.     {
  1259.     if (must_redraw)
  1260.         update_screen(0);
  1261.     else if (clear_cmdline || redraw_cmdline)
  1262.         showmode();        /* clear cmdline and show mode */
  1263.     showruler(FALSE);
  1264.     setcursor();
  1265.     emsg_on_display = FALSE;    /* may remove error message now */
  1266.     }
  1267. }
  1268.  
  1269. /*
  1270.  * Handle a CTRL-V or CTRL-Q typed in Insert mode.
  1271.  */
  1272.     static void
  1273. ins_ctrl_v()
  1274. {
  1275.     int        c;
  1276.  
  1277.     /* may need to redraw when no more chars available now */
  1278.     ins_redraw();
  1279.  
  1280.     if (redrawing() && !char_avail())
  1281.     edit_putchar('^', TRUE);
  1282.     AppendToRedobuff((char_u *)CTRL_V_STR);    /* CTRL-V */
  1283.  
  1284. #ifdef FEAT_CMDL_INFO
  1285.     add_to_showcmd_c(Ctrl_V);
  1286. #endif
  1287.  
  1288.     c = get_literal();
  1289. #ifdef FEAT_CMDL_INFO
  1290.     clear_showcmd();
  1291. #endif
  1292.     insert_special(c, FALSE, TRUE);
  1293. #ifdef FEAT_RIGHTLEFT
  1294.     revins_chars++;
  1295.     revins_legal++;
  1296. #endif
  1297. }
  1298.  
  1299. /*
  1300.  * Put a character directly onto the screen.  It's not stored in a buffer.
  1301.  * Used while handling CTRL-K, CTRL-V, etc. in Insert mode.
  1302.  */
  1303. static int  pc_char;
  1304. static int  pc_attr;
  1305. static int  pc_row;
  1306. static int  pc_col;
  1307.  
  1308.     void
  1309. edit_putchar(c, highlight)
  1310.     int        c;
  1311.     int        highlight;
  1312. {
  1313.     int        attr;
  1314.  
  1315.     if (ScreenLines != NULL)
  1316.     {
  1317.     update_topline();    /* just in case w_topline isn't valid */
  1318.     validate_cursor();
  1319.     if (highlight)
  1320.         attr = hl_attr(HLF_8);
  1321.     else
  1322.         attr = 0;
  1323.     pc_row = W_WINROW(curwin) + curwin->w_wrow;
  1324.     pc_col = W_WINCOL(curwin) + (
  1325. #ifdef FEAT_RIGHTLEFT
  1326.         curwin->w_p_rl ? (int)W_WIDTH(curwin) - 1 - curwin->w_wcol :
  1327. #endif
  1328.                              curwin->w_wcol);
  1329.     /* save the character to be able to put it back */
  1330.     pc_char = screen_getchar(pc_row, pc_col, &pc_attr);
  1331.     screen_putchar(c, pc_row, pc_col, attr);
  1332.     }
  1333. }
  1334.  
  1335. /*
  1336.  * Undo the previous edit_putchar().
  1337.  */
  1338.     void
  1339. edit_unputchar()
  1340. {
  1341.     if (pc_row >= msg_scrolled)
  1342.     screen_putchar(pc_char, pc_row - msg_scrolled, pc_col, pc_attr);
  1343. }
  1344.  
  1345. /*
  1346.  * Called when p_dollar is set: display a '$' at the end of the changed text
  1347.  * Only works when cursor is in the line that changes.
  1348.  */
  1349.     void
  1350. display_dollar(col)
  1351.     colnr_T    col;
  1352. {
  1353.     colnr_T save_col;
  1354.  
  1355.     if (!redrawing())
  1356.     return;
  1357.  
  1358.     cursor_off();
  1359.     save_col = curwin->w_cursor.col;
  1360.     curwin->w_cursor.col = col;
  1361. #ifdef FEAT_MBYTE
  1362.     if (has_mbyte)
  1363.     {
  1364.     char_u *p;
  1365.  
  1366.     /* If on the last byte of a multi-byte move to the first byte. */
  1367.     p = ml_get_curline();
  1368.     curwin->w_cursor.col -= (*mb_head_off)(p, p + col);
  1369.     }
  1370. #endif
  1371.     curs_columns(FALSE);        /* recompute w_wrow and w_wcol */
  1372.     if (curwin->w_wcol < W_WIDTH(curwin))
  1373.     {
  1374.     edit_putchar('$', FALSE);
  1375.     dollar_vcol = curwin->w_virtcol;
  1376.     }
  1377.     curwin->w_cursor.col = save_col;
  1378. }
  1379.  
  1380. /*
  1381.  * Call this function before moving the cursor from the normal insert position
  1382.  * in insert mode.
  1383.  */
  1384.     static void
  1385. undisplay_dollar()
  1386. {
  1387.     if (dollar_vcol)
  1388.     {
  1389.     dollar_vcol = 0;
  1390.     redrawWinline(curwin->w_cursor.lnum, FALSE);
  1391.     }
  1392. }
  1393.  
  1394. /*
  1395.  * Insert an indent (for <Tab> or CTRL-T) or delete an indent (for CTRL-D).
  1396.  * Keep the cursor on the same character.
  1397.  * type == INDENT_INC    increase indent (for CTRL-T or <Tab>)
  1398.  * type == INDENT_DEC    decrease indent (for CTRL-D)
  1399.  * type == INDENT_SET    set indent to "amount"
  1400.  * if round is TRUE, round the indent to 'shiftwidth' (only with _INC and _Dec).
  1401.  */
  1402.     void
  1403. change_indent(type, amount, round, replaced)
  1404.     int        type;
  1405.     int        amount;
  1406.     int        round;
  1407.     int        replaced;        /* replaced character, put on replace stack */
  1408. {
  1409.     int        vcol;
  1410.     int        last_vcol;
  1411.     int        insstart_less;        /* reduction for Insstart.col */
  1412.     int        new_cursor_col;
  1413.     int        i;
  1414.     char_u    *ptr;
  1415.     int        save_p_list;
  1416.     int        start_col;
  1417.     colnr_T    vc;
  1418. #ifdef FEAT_VREPLACE
  1419.     colnr_T    orig_col = 0;        /* init for GCC */
  1420.     char_u    *new_line, *orig_line = NULL;    /* init for GCC */
  1421.  
  1422.     /* VREPLACE mode needs to know what the line was like before changing */
  1423.     if (State & VREPLACE_FLAG)
  1424.     {
  1425.     orig_line = vim_strsave(ml_get_curline());  /* Deal with NULL below */
  1426.     orig_col = curwin->w_cursor.col;
  1427.     }
  1428. #endif
  1429.  
  1430.     /* for the following tricks we don't want list mode */
  1431.     save_p_list = curwin->w_p_list;
  1432.     curwin->w_p_list = FALSE;
  1433.     vc = getvcol_nolist(&curwin->w_cursor);
  1434.     vcol = vc;
  1435.  
  1436.     /*
  1437.      * For Replace mode we need to fix the replace stack later, which is only
  1438.      * possible when the cursor is in the indent.  Remember the number of
  1439.      * characters before the cursor if it's possible.
  1440.      */
  1441.     start_col = curwin->w_cursor.col;
  1442.  
  1443.     /* determine offset from first non-blank */
  1444.     new_cursor_col = curwin->w_cursor.col;
  1445.     beginline(BL_WHITE);
  1446.     new_cursor_col -= curwin->w_cursor.col;
  1447.  
  1448.     insstart_less = curwin->w_cursor.col;
  1449.  
  1450.     /*
  1451.      * If the cursor is in the indent, compute how many screen columns the
  1452.      * cursor is to the left of the first non-blank.
  1453.      */
  1454.     if (new_cursor_col < 0)
  1455.     vcol = get_indent() - vcol;
  1456.  
  1457.     if (new_cursor_col > 0)        /* can't fix replace stack */
  1458.     start_col = -1;
  1459.  
  1460.     /*
  1461.      * Set the new indent.  The cursor will be put on the first non-blank.
  1462.      */
  1463.     if (type == INDENT_SET)
  1464.     (void)set_indent(amount, SIN_CHANGED);
  1465.     else
  1466.     shift_line(type == INDENT_DEC, round, 1);
  1467.     insstart_less -= curwin->w_cursor.col;
  1468.  
  1469.     /*
  1470.      * Try to put cursor on same character.
  1471.      * If the cursor is at or after the first non-blank in the line,
  1472.      * compute the cursor column relative to the column of the first
  1473.      * non-blank character.
  1474.      * If we are not in insert mode, leave the cursor on the first non-blank.
  1475.      * If the cursor is before the first non-blank, position it relative
  1476.      * to the first non-blank, counted in screen columns.
  1477.      */
  1478.     if (new_cursor_col >= 0)
  1479.     {
  1480.     /*
  1481.      * When changing the indent while the cursor is touching it, reset
  1482.      * Insstart_col to 0.
  1483.      */
  1484.     if (new_cursor_col == 0)
  1485.         insstart_less = MAXCOL;
  1486.     new_cursor_col += curwin->w_cursor.col;
  1487.     }
  1488.     else if (!(State & INSERT))
  1489.     new_cursor_col = curwin->w_cursor.col;
  1490.     else
  1491.     {
  1492.     /*
  1493.      * Compute the screen column where the cursor should be.
  1494.      */
  1495.     vcol = get_indent() - vcol;
  1496.     curwin->w_virtcol = (vcol < 0) ? 0 : vcol;
  1497.  
  1498.     /*
  1499.      * Advance the cursor until we reach the right screen column.
  1500.      */
  1501.     vcol = last_vcol = 0;
  1502.     new_cursor_col = -1;
  1503.     ptr = ml_get_curline();
  1504.     while (vcol <= (int)curwin->w_virtcol)
  1505.     {
  1506.         last_vcol = vcol;
  1507. #ifdef FEAT_MBYTE
  1508.         if (has_mbyte)
  1509.         new_cursor_col += (*mb_ptr2len_check)(ptr + new_cursor_col);
  1510.         else
  1511. #endif
  1512.         ++new_cursor_col;
  1513.         vcol += lbr_chartabsize(ptr + new_cursor_col, (colnr_T)vcol);
  1514.     }
  1515.     vcol = last_vcol;
  1516.  
  1517.     /*
  1518.      * May need to insert spaces to be able to position the cursor on
  1519.      * the right screen column.
  1520.      */
  1521.     if (vcol != (int)curwin->w_virtcol)
  1522.     {
  1523.         curwin->w_cursor.col = new_cursor_col;
  1524.         i = (int)curwin->w_virtcol - vcol;
  1525.         ptr = alloc(i + 1);
  1526.         if (ptr != NULL)
  1527.         {
  1528.         new_cursor_col += i;
  1529.         ptr[i] = NUL;
  1530.         while (--i >= 0)
  1531.             ptr[i] = ' ';
  1532.         ins_str(ptr);
  1533.         vim_free(ptr);
  1534.         }
  1535.     }
  1536.  
  1537.     /*
  1538.      * When changing the indent while the cursor is in it, reset
  1539.      * Insstart_col to 0.
  1540.      */
  1541.     insstart_less = MAXCOL;
  1542.     }
  1543.  
  1544.     curwin->w_p_list = save_p_list;
  1545.  
  1546.     if (new_cursor_col <= 0)
  1547.     curwin->w_cursor.col = 0;
  1548.     else
  1549.     curwin->w_cursor.col = new_cursor_col;
  1550.     curwin->w_set_curswant = TRUE;
  1551.     changed_cline_bef_curs();
  1552.  
  1553.     /*
  1554.      * May have to adjust the start of the insert.
  1555.      */
  1556.     if (State & INSERT)
  1557.     {
  1558.     if (curwin->w_cursor.lnum == Insstart.lnum && Insstart.col != 0)
  1559.     {
  1560.         if ((int)Insstart.col <= insstart_less)
  1561.         Insstart.col = 0;
  1562.         else
  1563.         Insstart.col -= insstart_less;
  1564.     }
  1565.     if ((int)ai_col <= insstart_less)
  1566.         ai_col = 0;
  1567.     else
  1568.         ai_col -= insstart_less;
  1569.     }
  1570.  
  1571.     /*
  1572.      * For REPLACE mode, may have to fix the replace stack, if it's possible.
  1573.      * If the number of characters before the cursor decreased, need to pop a
  1574.      * few characters from the replace stack.
  1575.      * If the number of characters before the cursor increased, need to push a
  1576.      * few NULs onto the replace stack.
  1577.      */
  1578.     if (REPLACE_NORMAL(State) && start_col >= 0)
  1579.     {
  1580.     while (start_col > (int)curwin->w_cursor.col)
  1581.     {
  1582.         replace_join(0);        /* remove a NUL from the replace stack */
  1583.         --start_col;
  1584.     }
  1585.     while (start_col < (int)curwin->w_cursor.col || replaced)
  1586.     {
  1587.         replace_push(NUL);
  1588.         if (replaced)
  1589.         {
  1590.         replace_push(replaced);
  1591.         replaced = NUL;
  1592.         }
  1593.         ++start_col;
  1594.     }
  1595.     }
  1596.  
  1597. #ifdef FEAT_VREPLACE
  1598.     /*
  1599.      * For VREPLACE mode, we also have to fix the replace stack.  In this case
  1600.      * it is always possible because we backspace over the whole line and then
  1601.      * put it back again the way we wanted it.
  1602.      */
  1603.     if (State & VREPLACE_FLAG)
  1604.     {
  1605.     /* If orig_line didn't allocate, just return.  At least we did the job,
  1606.      * even if you can't backspace.
  1607.      */
  1608.     if (orig_line == NULL)
  1609.         return;
  1610.  
  1611.     /* Save new line */
  1612.     new_line = vim_strsave(ml_get_curline());
  1613.     if (new_line == NULL)
  1614.         return;
  1615.  
  1616.     /* We only put back the new line up to the cursor */
  1617.     new_line[curwin->w_cursor.col] = NUL;
  1618.  
  1619.     /* Put back original line */
  1620.     ml_replace(curwin->w_cursor.lnum, orig_line, FALSE);
  1621.     curwin->w_cursor.col = orig_col;
  1622.  
  1623.     /* Backspace from cursor to start of line */
  1624.     backspace_until_column(0);
  1625.  
  1626.     /* Insert new stuff into line again */
  1627.     ins_bytes(new_line);
  1628.  
  1629.     vim_free(new_line);
  1630.     }
  1631. #endif
  1632. }
  1633.  
  1634. /*
  1635.  * Truncate the space at the end of a line.  This is to be used only in an
  1636.  * insert mode.  It handles fixing the replace stack for REPLACE and VREPLACE
  1637.  * modes.
  1638.  */
  1639.     void
  1640. truncate_spaces(line)
  1641.     char_u  *line;
  1642. {
  1643.     int        i;
  1644.  
  1645.     /* find start of trailing white space */
  1646.     for (i = (int)STRLEN(line) - 1; i >= 0 && vim_iswhite(line[i]); i--)
  1647.     {
  1648.     if (State & REPLACE_FLAG)
  1649.         replace_join(0);        /* remove a NUL from the replace stack */
  1650.     }
  1651.     line[i + 1] = NUL;
  1652. }
  1653.  
  1654. #if defined(FEAT_VREPLACE) || defined(FEAT_INS_EXPAND) \
  1655.     || defined(FEAT_COMMENTS) || defined(PROTO)
  1656. /*
  1657.  * Backspace the cursor until the given column.  Handles REPLACE and VREPLACE
  1658.  * modes correctly.  May also be used when not in insert mode at all.
  1659.  */
  1660.     void
  1661. backspace_until_column(col)
  1662.     int        col;
  1663. {
  1664.     while ((int)curwin->w_cursor.col > col)
  1665.     {
  1666.     curwin->w_cursor.col--;
  1667.     if (State & REPLACE_FLAG)
  1668.         replace_do_bs();
  1669.     else
  1670.         (void)del_char(FALSE);
  1671.     }
  1672. }
  1673. #endif
  1674.  
  1675. #if defined(FEAT_INS_EXPAND) || defined(PROTO)
  1676. /*
  1677.  * Is the character 'c' a valid key to go to or keep us in CTRL-X mode?
  1678.  * This depends on the current mode.
  1679.  */
  1680.     int
  1681. vim_is_ctrl_x_key(c)
  1682.     int        c;
  1683. {
  1684.     /* Always allow ^R - let it's results then be checked */
  1685.     if (c == Ctrl_R)
  1686.     return TRUE;
  1687.  
  1688.     switch (ctrl_x_mode)
  1689.     {
  1690.     case 0:            /* Not in any CTRL-X mode */
  1691.         return (c == Ctrl_N || c == Ctrl_P || c == Ctrl_X);
  1692.     case CTRL_X_NOT_DEFINED_YET:
  1693.         return (       c == Ctrl_X || c == Ctrl_Y || c == Ctrl_E
  1694.             || c == Ctrl_L || c == Ctrl_F || c == Ctrl_RSB
  1695.             || c == Ctrl_I || c == Ctrl_D || c == Ctrl_P
  1696.             || c == Ctrl_N || c == Ctrl_T || c == Ctrl_V);
  1697.     case CTRL_X_SCROLL:
  1698.         return (c == Ctrl_Y || c == Ctrl_E);
  1699.     case CTRL_X_WHOLE_LINE:
  1700.         return (c == Ctrl_L || c == Ctrl_P || c == Ctrl_N);
  1701.     case CTRL_X_FILES:
  1702.         return (c == Ctrl_F || c == Ctrl_P || c == Ctrl_N);
  1703.     case CTRL_X_DICTIONARY:
  1704.         return (c == Ctrl_K || c == Ctrl_P || c == Ctrl_N);
  1705.     case CTRL_X_THESAURUS:
  1706.         return (c == Ctrl_T || c == Ctrl_P || c == Ctrl_N);
  1707.     case CTRL_X_TAGS:
  1708.         return (c == Ctrl_RSB || c == Ctrl_P || c == Ctrl_N);
  1709. #ifdef FEAT_FIND_ID
  1710.     case CTRL_X_PATH_PATTERNS:
  1711.         return (c == Ctrl_P || c == Ctrl_N);
  1712.     case CTRL_X_PATH_DEFINES:
  1713.         return (c == Ctrl_D || c == Ctrl_P || c == Ctrl_N);
  1714. #endif
  1715.     case CTRL_X_CMDLINE:
  1716.         return (c == Ctrl_V || c == Ctrl_P || c == Ctrl_N || c == Ctrl_X);
  1717.     }
  1718.     EMSG(_(e_internal));
  1719.     return FALSE;
  1720. }
  1721.  
  1722. /*
  1723.  * This is like ins_compl_add(), but if ic and inf are set, then the
  1724.  * case of the originally typed text is used, and the case of the completed
  1725.  * text is infered, ie this tries to work out what case you probably wanted
  1726.  * the rest of the word to be in -- webb
  1727.  */
  1728.     int
  1729. ins_compl_add_infercase(str, len, fname, dir, reuse)
  1730.     char_u    *str;
  1731.     int        len;
  1732.     char_u    *fname;
  1733.     int        dir;
  1734.     int        reuse;
  1735. {
  1736.     int        has_lower = FALSE;
  1737.     int        was_letter = FALSE;
  1738.     int        idx;
  1739.  
  1740.     if (p_ic && curbuf->b_p_inf && len < IOSIZE)
  1741.     {
  1742.     /* Infer case of completed part -- webb */
  1743.     /* Use IObuff, str would change text in buffer! */
  1744.     STRNCPY(IObuff, str, len);
  1745.     IObuff[len] = NUL;
  1746.  
  1747.     /* Rule 1: Were any chars converted to lower? */
  1748.     for (idx = 0; idx < completion_length; ++idx)
  1749.     {
  1750.         if (islower(original_text[idx]))
  1751.         {
  1752.         has_lower = TRUE;
  1753.         if (isupper(IObuff[idx]))
  1754.         {
  1755.             /* Rule 1 is satisfied */
  1756.             for (idx = completion_length; idx < len; ++idx)
  1757.             IObuff[idx] = TO_LOWER(IObuff[idx]);
  1758.             break;
  1759.         }
  1760.         }
  1761.     }
  1762.  
  1763.     /*
  1764.      * Rule 2: No lower case, 2nd consecutive letter converted to
  1765.      * upper case.
  1766.      */
  1767.     if (!has_lower)
  1768.     {
  1769.         for (idx = 0; idx < completion_length; ++idx)
  1770.         {
  1771.         if (was_letter && isupper(original_text[idx])
  1772.                               && islower(IObuff[idx]))
  1773.         {
  1774.             /* Rule 2 is satisfied */
  1775.             for (idx = completion_length; idx < len; ++idx)
  1776.             IObuff[idx] = TO_UPPER(IObuff[idx]);
  1777.             break;
  1778.         }
  1779.         was_letter = isalpha(original_text[idx]);
  1780.         }
  1781.     }
  1782.  
  1783.     /* Copy the original case of the part we typed */
  1784.     STRNCPY(IObuff, original_text, completion_length);
  1785.  
  1786.     return ins_compl_add(IObuff, len, fname, dir, reuse);
  1787.     }
  1788.     return ins_compl_add(str, len, fname, dir, reuse);
  1789. }
  1790.  
  1791. /*
  1792.  * Add a match to the list of matches.
  1793.  * If the given string is already in the list of completions, then return
  1794.  * FAIL, otherwise add it to the list and return OK.  If there is an error,
  1795.  * maybe because alloc returns NULL, then RET_ERROR is returned -- webb.
  1796.  */
  1797.     static int
  1798. ins_compl_add(str, len, fname, dir, reuse)
  1799.     char_u    *str;
  1800.     int        len;
  1801.     char_u    *fname;
  1802.     int        dir;
  1803.     int        reuse;
  1804. {
  1805.     struct Completion *match;
  1806.  
  1807.     ui_breakcheck();
  1808.     if (got_int)
  1809.     return RET_ERROR;
  1810.     if (len < 0)
  1811.     len = (int)STRLEN(str);
  1812.  
  1813.     /*
  1814.      * If the same match is already present, don't add it.
  1815.      */
  1816.     if (first_match != NULL)
  1817.     {
  1818.     match = first_match;
  1819.     do
  1820.     {
  1821.         if (    !(match->original & ORIGINAL_TEXT)
  1822.             && STRNCMP(match->str, str, (size_t)len) == 0
  1823.             && match->str[len] == NUL)
  1824.         return FAIL;
  1825.         match = match->next;
  1826.     } while (match != NULL && match != first_match);
  1827.     }
  1828.  
  1829.     /*
  1830.      * Allocate a new match structure.
  1831.      * Copy the values to the new match structure.
  1832.      */
  1833.     match = (struct Completion *)alloc((unsigned)sizeof(struct Completion));
  1834.     if (match == NULL)
  1835.     return RET_ERROR;
  1836.     match->number = -1;
  1837.     if (reuse & ORIGINAL_TEXT)
  1838.     {
  1839.     match->number = 0;
  1840.     match->str = original_text;
  1841.     }
  1842.     else if ((match->str = vim_strnsave(str, len)) == NULL)
  1843.     {
  1844.     vim_free(match);
  1845.     return RET_ERROR;
  1846.     }
  1847.     /* match-fname is:
  1848.      * - curr_match->fname if it is a string equal to fname.
  1849.      * - a copy of fname, FREE_FNAME is set to free later THE allocated mem.
  1850.      * - NULL otherwise.    --Acevedo */
  1851.     if (fname && curr_match && curr_match->fname
  1852.           && STRCMP(fname, curr_match->fname) == 0)
  1853.     match->fname = curr_match->fname;
  1854.     else if (fname && (match->fname = vim_strsave(fname)) != NULL)
  1855.     reuse |= FREE_FNAME;
  1856.     else
  1857.     match->fname = NULL;
  1858.     match->original = reuse;
  1859.  
  1860.     /*
  1861.      * Link the new match structure in the list of matches.
  1862.      */
  1863.     if (first_match == NULL)
  1864.     match->next = match->prev = NULL;
  1865.     else if (dir == FORWARD)
  1866.     {
  1867.     match->next = curr_match->next;
  1868.     match->prev = curr_match;
  1869.     }
  1870.     else    /* BACKWARD */
  1871.     {
  1872.     match->next = curr_match;
  1873.     match->prev = curr_match->prev;
  1874.     }
  1875.     if (match->next)
  1876.     match->next->prev = match;
  1877.     if (match->prev)
  1878.     match->prev->next = match;
  1879.     else    /* if there's nothing before, it is the first match */
  1880.     first_match = match;
  1881.     curr_match = match;
  1882.  
  1883.     return OK;
  1884. }
  1885.  
  1886. /*
  1887.  * Add an array of matches to the list of matches.
  1888.  * Frees matches[].
  1889.  */
  1890.     static void
  1891. ins_compl_add_matches(num_matches, matches, dir)
  1892.     int        num_matches;
  1893.     char_u    **matches;
  1894.     int        dir;
  1895. {
  1896.     int        i;
  1897.     int        add_r = OK;
  1898.     int        ldir = dir;
  1899.  
  1900.     for (i = 0; i < num_matches && add_r != RET_ERROR; i++)
  1901.     if ((add_r = ins_compl_add(matches[i], -1, NULL, ldir, 0)) == OK)
  1902.         /* if dir was BACKWARD then honor it just once */
  1903.         ldir = FORWARD;
  1904.     FreeWild(num_matches, matches);
  1905. }
  1906.  
  1907. /* Make the completion list cyclic.
  1908.  * Return the number of matches (excluding the original).
  1909.  */
  1910.     static int
  1911. ins_compl_make_cyclic()
  1912. {
  1913.     struct Completion *match;
  1914.     int        count = 0;
  1915.  
  1916.     if (first_match != NULL)
  1917.     {
  1918.     /*
  1919.      * Find the end of the list.
  1920.      */
  1921.     match = first_match;
  1922.     /* there's always an entry for the original_text, it doesn't count. */
  1923.     while (match->next != NULL && match->next != first_match)
  1924.     {
  1925.         match = match->next;
  1926.         ++count;
  1927.     }
  1928.     match->next = first_match;
  1929.     first_match->prev = match;
  1930.     }
  1931.     return count;
  1932. }
  1933.  
  1934. #define DICT_FIRST    (1)    /* use just first element in "dict" */
  1935. #define DICT_EXACT    (2)    /* "dict" is the exact name of a file */
  1936. /*
  1937.  * Add any identifiers that match the given pattern to the list of
  1938.  * completions.
  1939.  */
  1940.     static void
  1941. ins_compl_dictionaries(dict, pat, dir, flags, thesaurus)
  1942.     char_u    *dict;
  1943.     char_u    *pat;
  1944.     int        dir;
  1945.     int        flags;
  1946.     int        thesaurus;
  1947. {
  1948.     char_u    *ptr;
  1949.     char_u    *buf;
  1950.     FILE    *fp;
  1951.     regmatch_T    regmatch;
  1952.     int        add_r;
  1953.     char_u    **files;
  1954.     int        count;
  1955.     int        i;
  1956.     int        save_p_scs;
  1957.  
  1958.     buf = alloc(LSIZE);
  1959.     /* If 'infercase' is set, don't use 'smartcase' here */
  1960.     save_p_scs = p_scs;
  1961.     if (curbuf->b_p_inf)
  1962.     p_scs = FALSE;
  1963.     regmatch.regprog = vim_regcomp(pat, (int)p_magic);
  1964.     /* ignore case depends on 'ignorecase', 'smartcase' and "pat" */
  1965.     regmatch.rm_ic = ignorecase(pat);
  1966.     while (buf != NULL && regmatch.regprog != NULL && *dict != NUL
  1967.                && !got_int && !completion_interrupted)
  1968.     {
  1969.     /* copy one dictionary file name into buf */
  1970.     if (flags == DICT_EXACT)
  1971.     {
  1972.         count = 1;
  1973.         files = &dict;
  1974.     }
  1975.     else
  1976.     {
  1977.         /* Expand wildcards in the dictionary name, but do not allow
  1978.          * backticks (for security, the 'dict' option may have been set in
  1979.          * a modeline). */
  1980.         copy_option_part(&dict, buf, LSIZE, ",");
  1981.         if (vim_strchr(buf, '`') != NULL
  1982.             || expand_wildcards(1, &buf, &count, &files,
  1983.                              EW_FILE|EW_SILENT) != OK)
  1984.         count = 0;
  1985.     }
  1986.  
  1987.     for (i = 0; i < count && !got_int && !completion_interrupted; i++)
  1988.     {
  1989.         fp = mch_fopen((char *)files[i], "r");  /* open dictionary file */
  1990.         if (flags != DICT_EXACT)
  1991.         {
  1992.         sprintf((char*)IObuff, _("Scanning dictionary: %s"),
  1993.                                 (char *)files[i]);
  1994.         msg_trunc_attr(IObuff, TRUE, hl_attr(HLF_R));
  1995.         }
  1996.  
  1997.         if (fp != NULL)
  1998.         {
  1999.         /*
  2000.          * Read dictionary file line by line.
  2001.          * Check each line for a match.
  2002.          */
  2003.         while (!got_int && !completion_interrupted
  2004.                 && !vim_fgets(buf, LSIZE, fp))
  2005.         {
  2006.             ptr = buf;
  2007.             while (vim_regexec(®match, buf, (colnr_T)(ptr - buf)))
  2008.             {
  2009.             ptr = regmatch.startp[0];
  2010.             ptr = find_word_end(ptr);
  2011.             add_r = ins_compl_add_infercase(regmatch.startp[0],
  2012.                           (int)(ptr - regmatch.startp[0]),
  2013.                                 files[i], dir, 0);
  2014.             if (thesaurus)
  2015.             {
  2016.                 char_u *wstart;
  2017.  
  2018.                 /*
  2019.                  * Add the other matches on the line
  2020.                  */
  2021.                 while (!got_int)
  2022.                 {
  2023.                 /* Find start of the next word.  Skip white
  2024.                  * space and punctuation. */
  2025.                 ptr = find_word_start(ptr);
  2026.                 if (*ptr == NUL || *ptr == NL)
  2027.                     break;
  2028.                 wstart = ptr;
  2029.  
  2030.                 /* Find end of the word and add it. */
  2031.                 ptr = find_word_end(ptr);
  2032.                 add_r = ins_compl_add_infercase(wstart,
  2033.                     (int)(ptr - wstart), files[i], dir, 0);
  2034.                 }
  2035.             }
  2036.             if (add_r == OK)
  2037.                 /* if dir was BACKWARD then honor it just once */
  2038.                 dir = FORWARD;
  2039.             else if (add_r == RET_ERROR)
  2040.                 break;
  2041.             /* avoid expensive call to vim_regexec() when at end
  2042.              * of line */
  2043.             if (*ptr == '\n' || got_int)
  2044.                 break;
  2045.             }
  2046.             line_breakcheck();
  2047.             ins_compl_check_keys();
  2048.         }
  2049.         fclose(fp);
  2050.         }
  2051.     }
  2052.     if (flags != DICT_EXACT)
  2053.         FreeWild(count, files);
  2054.     if (flags)
  2055.         break;
  2056.     }
  2057.     p_scs = save_p_scs;
  2058.     vim_free(regmatch.regprog);
  2059.     vim_free(buf);
  2060. }
  2061.  
  2062. /*
  2063.  * Find the start of the next word.
  2064.  * Returns a pointer to the first char of the word.  Also stops at a NUL.
  2065.  */
  2066.     char_u *
  2067. find_word_start(ptr)
  2068.     char_u    *ptr;
  2069. {
  2070. #ifdef FEAT_MBYTE
  2071.     if (has_mbyte)
  2072.     while (*ptr != NUL && *ptr != '\n' && mb_get_class(ptr) <= 1)
  2073.         ptr += (*mb_ptr2len_check)(ptr);
  2074.     else
  2075. #endif
  2076.     while (*ptr != NUL && *ptr != '\n' && !vim_iswordc(*ptr))
  2077.         ++ptr;
  2078.     return ptr;
  2079. }
  2080.  
  2081. /*
  2082.  * Find the end of the word.  Assumes it starts inside a word.
  2083.  * Returns a pointer to just after the word.
  2084.  */
  2085.     char_u *
  2086. find_word_end(ptr)
  2087.     char_u    *ptr;
  2088. {
  2089. #ifdef FEAT_MBYTE
  2090.     int        start_class;
  2091.  
  2092.     if (has_mbyte)
  2093.     {
  2094.     start_class = mb_get_class(ptr);
  2095.     if (start_class > 1)
  2096.         while (*ptr != NUL)
  2097.         {
  2098.         ptr += (*mb_ptr2len_check)(ptr);
  2099.         if (mb_get_class(ptr) != start_class)
  2100.             break;
  2101.         }
  2102.     }
  2103.     else
  2104. #endif
  2105.     while (vim_iswordc(*ptr))
  2106.         ++ptr;
  2107.     return ptr;
  2108. }
  2109.  
  2110. /*
  2111.  * Free the list of completions
  2112.  */
  2113.     static void
  2114. ins_compl_free()
  2115. {
  2116.     struct Completion *match;
  2117.  
  2118.     vim_free(complete_pat);
  2119.     complete_pat = NULL;
  2120.  
  2121.     if (first_match == NULL)
  2122.     return;
  2123.     curr_match = first_match;
  2124.     do
  2125.     {
  2126.     match = curr_match;
  2127.     curr_match = curr_match->next;
  2128.     vim_free(match->str);
  2129.     /* several entries may use the same fname, free it just once. */
  2130.     if (match->original & FREE_FNAME)
  2131.         vim_free(match->fname);
  2132.     vim_free(match);
  2133.     } while (curr_match != NULL && curr_match != first_match);
  2134.     first_match = curr_match = NULL;
  2135. }
  2136.  
  2137.     static void
  2138. ins_compl_clear()
  2139. {
  2140.     continue_status = 0;
  2141.     started_completion = FALSE;
  2142.     completion_matches = 0;
  2143.     vim_free(complete_pat);
  2144.     complete_pat = NULL;
  2145.     save_sm = -1;
  2146.     edit_submode_extra = NULL;
  2147. }
  2148.  
  2149. /*
  2150.  * Prepare for Insert mode completion, or stop it.
  2151.  */
  2152.     static void
  2153. ins_compl_prep(c)
  2154.     int        c;
  2155. {
  2156.     char_u    *ptr;
  2157.     char_u    *tmp_ptr;
  2158.     int        temp;
  2159.     int        want_cindent;
  2160.  
  2161.     /* Forget any previous 'special' messages if this is actually
  2162.      * a ^X mode key - bar ^R, in which case we wait to see what it gives us.
  2163.      */
  2164.     if (c != Ctrl_R  &&  vim_is_ctrl_x_key(c))
  2165.     edit_submode_extra = NULL;
  2166.  
  2167.     /* Ignore end of Select mode mapping */
  2168.     if (c == K_SELECT)
  2169.     return;
  2170.  
  2171.     if (ctrl_x_mode == CTRL_X_NOT_DEFINED_YET)
  2172.     {
  2173.     /*
  2174.      * We have just typed CTRL-X and aren't quite sure which CTRL-X mode
  2175.      * it will be yet.  Now we decide.
  2176.      */
  2177.     switch (c)
  2178.     {
  2179.         case Ctrl_E:
  2180.         case Ctrl_Y:
  2181.         ctrl_x_mode = CTRL_X_SCROLL;
  2182.         if (!(State & REPLACE_FLAG))
  2183.             edit_submode = (char_u *)_(" (insert) Scroll (^E/^Y)");
  2184.         else
  2185.             edit_submode = (char_u *)_(" (replace) Scroll (^E/^Y)");
  2186.         edit_submode_pre = NULL;
  2187.         showmode();
  2188.         break;
  2189.         case Ctrl_L:
  2190.         ctrl_x_mode = CTRL_X_WHOLE_LINE;
  2191.         break;
  2192.         case Ctrl_F:
  2193.         ctrl_x_mode = CTRL_X_FILES;
  2194.         break;
  2195.         case Ctrl_K:
  2196.         ctrl_x_mode = CTRL_X_DICTIONARY;
  2197.         break;
  2198.         case Ctrl_R:
  2199.         /* Simply allow ^R to happen without affecting ^X mode */
  2200.         break;
  2201.         case Ctrl_T:
  2202.         ctrl_x_mode = CTRL_X_THESAURUS;
  2203.         break;
  2204.         case Ctrl_RSB:
  2205.         ctrl_x_mode = CTRL_X_TAGS;
  2206.         break;
  2207. #ifdef FEAT_FIND_ID
  2208.         case Ctrl_I:
  2209.         case K_S_TAB:
  2210.         ctrl_x_mode = CTRL_X_PATH_PATTERNS;
  2211.         break;
  2212.         case Ctrl_D:
  2213.         ctrl_x_mode = CTRL_X_PATH_DEFINES;
  2214.         break;
  2215. #endif
  2216.         case Ctrl_V:
  2217.         ctrl_x_mode = CTRL_X_CMDLINE;
  2218.         break;
  2219.         case Ctrl_P:
  2220.         case Ctrl_N:
  2221.         /* ^X^P means LOCAL expansion if nothing interrupted (eg we
  2222.          * just started ^X mode, or there were enough ^X's to cancel
  2223.          * the previous mode, say ^X^F^X^X^P or ^P^X^X^X^P, see below)
  2224.          * do normal expansion when interrupting a different mode (say
  2225.          * ^X^F^X^P or ^P^X^X^P, see below)
  2226.          * nothing changes if interrupting mode 0, (eg, the flag
  2227.          * doesn't change when going to ADDING mode  -- Acevedo */
  2228.         if (!(continue_status & CONT_INTRPT))
  2229.             continue_status |= CONT_LOCAL;
  2230.         else if (continue_mode != 0)
  2231.             continue_status &= ~CONT_LOCAL;
  2232.         /* FALLTHROUGH */
  2233.         default:
  2234.         /* if we have typed at least 2 ^X's... for modes != 0, we set
  2235.          * continue_status = 0 (eg, as if we had just started ^X mode)
  2236.          * for mode 0, we set continue_mode to an impossible value, in
  2237.          * both cases ^X^X can be used to restart the same mode
  2238.          * (avoiding ADDING mode).   Undocumented feature:
  2239.          * In a mode != 0 ^X^P and ^X^X^P start 'complete' and local
  2240.          * ^P expansions respectively.    In mode 0 an extra ^X is
  2241.          * needed since ^X^P goes to ADDING mode  -- Acevedo */
  2242.         if (c == Ctrl_X)
  2243.         {
  2244.             if (continue_mode != 0)
  2245.             continue_status = 0;
  2246.             else
  2247.             continue_mode = CTRL_X_NOT_DEFINED_YET;
  2248.         }
  2249.         ctrl_x_mode = 0;
  2250.         edit_submode = NULL;
  2251.         showmode();
  2252.         break;
  2253.     }
  2254.     }
  2255.     else if (ctrl_x_mode != 0)
  2256.     {
  2257.     /* We're already in CTRL-X mode, do we stay in it? */
  2258.     if (!vim_is_ctrl_x_key(c))
  2259.     {
  2260.         if (ctrl_x_mode == CTRL_X_SCROLL)
  2261.         ctrl_x_mode = 0;
  2262.         else
  2263.         ctrl_x_mode = CTRL_X_FINISHED;
  2264.         edit_submode = NULL;
  2265.     }
  2266.     showmode();
  2267.     }
  2268.  
  2269.     if (started_completion || ctrl_x_mode == CTRL_X_FINISHED)
  2270.     {
  2271.     /* Show error message from attempted keyword completion (probably
  2272.      * 'Pattern not found') until another key is hit, then go back to
  2273.      * showing what mode we are in.
  2274.      */
  2275.     showmode();
  2276.     if ((ctrl_x_mode == 0 && c != Ctrl_N && c != Ctrl_P && c != Ctrl_R)
  2277.         || ctrl_x_mode == CTRL_X_FINISHED)
  2278.     {
  2279.         /* Get here when we have finished typing a sequence of ^N and
  2280.          * ^P or other completion characters in CTRL-X mode.  Free up
  2281.          * memory that was used, and make sure we can redo the insert.
  2282.          */
  2283.         if (curr_match != NULL)
  2284.         {
  2285.         /*
  2286.          * If any of the original typed text has been changed,
  2287.          * eg when ignorecase is set, we must add back-spaces to
  2288.          * the redo buffer.  We add as few as necessary to delete
  2289.          * just the part of the original text that has changed.
  2290.          */
  2291.         ptr = curr_match->str;
  2292.         tmp_ptr = original_text;
  2293.         while (*tmp_ptr && *tmp_ptr == *ptr)
  2294.         {
  2295.             ++tmp_ptr;
  2296.             ++ptr;
  2297.         }
  2298.         for (temp = 0; tmp_ptr[temp]; ++temp)
  2299.             AppendCharToRedobuff(K_BS);
  2300.         AppendToRedobuffLit(ptr);
  2301.         }
  2302.  
  2303. #ifdef FEAT_CINDENT
  2304.         want_cindent = (can_cindent && cindent_on());
  2305. #endif
  2306.         /*
  2307.          * When completing whole lines: fix indent for 'cindent'.
  2308.          * Otherwise, break line if it's too long.
  2309.          */
  2310.         if (continue_mode == CTRL_X_WHOLE_LINE)
  2311.         {
  2312. #ifdef FEAT_CINDENT
  2313.         /* re-indent the current line */
  2314.         if (want_cindent)
  2315.         {
  2316.             do_c_expr_indent();
  2317.             want_cindent = FALSE;    /* don't do it again */
  2318.         }
  2319. #endif
  2320.         }
  2321.         else
  2322.         {
  2323.         /* put the cursor on the last char, for 'tw' formatting */
  2324.         curwin->w_cursor.col--;
  2325.         if (stop_arrow() == OK)
  2326.             insertchar(NUL, 0, -1);
  2327.         curwin->w_cursor.col++;
  2328.         }
  2329.  
  2330.         ins_compl_free();
  2331.         started_completion = FALSE;
  2332.         completion_matches = 0;
  2333.         msg_clr_cmdline();        /* necessary for "noshowmode" */
  2334.         ctrl_x_mode = 0;
  2335.         p_sm = save_sm;
  2336.         if (edit_submode != NULL)
  2337.         {
  2338.         edit_submode = NULL;
  2339.         showmode();
  2340.         }
  2341.  
  2342. #ifdef FEAT_CINDENT
  2343.         /*
  2344.          * Indent now if a key was typed that is in 'cinkeys'.
  2345.          */
  2346.         if (want_cindent && in_cinkeys(KEY_COMPLETE, ' ', inindent(0)))
  2347.         do_c_expr_indent();
  2348. #endif
  2349.     }
  2350.     }
  2351.  
  2352.     /* reset continue_* if we left expansion-mode, if we stay they'll be
  2353.      * (re)set properly in ins_complete() */
  2354.     if (!vim_is_ctrl_x_key(c))
  2355.     {
  2356.     continue_status = 0;
  2357.     continue_mode = 0;
  2358.     }
  2359. }
  2360.  
  2361. /*
  2362.  * Loops through the list of windows, loaded-buffers or non-loaded-buffers
  2363.  * (depending on flag) starting from buf and looking for a non-scanned
  2364.  * buffer (other than curbuf).    curbuf is special, if it is called with
  2365.  * buf=curbuf then it has to be the first call for a given flag/expansion.
  2366.  *
  2367.  * Returns the buffer to scan, if any, otherwise returns curbuf -- Acevedo
  2368.  */
  2369.     static buf_T *
  2370. ins_compl_next_buf(buf, flag)
  2371.     buf_T    *buf;
  2372.     int        flag;
  2373. {
  2374. #ifdef FEAT_WINDOWS
  2375.     static win_T *wp;
  2376. #endif
  2377.  
  2378.     if (flag == 'w')        /* just windows */
  2379.     {
  2380. #ifdef FEAT_WINDOWS
  2381.     if (buf == curbuf)    /* first call for this flag/expansion */
  2382.         wp = curwin;
  2383.     while ((wp = wp->w_next != NULL ? wp->w_next : firstwin) != curwin
  2384.         && wp->w_buffer->b_scanned)
  2385.         ;
  2386.     buf = wp->w_buffer;
  2387. #else
  2388.     buf = curbuf;
  2389. #endif
  2390.     }
  2391.     else
  2392.     /* 'b' (just loaded buffers), 'u' (just non-loaded buffers) or 'U'
  2393.      * (unlisted buffers)
  2394.      * When completing whole lines skip unloaded buffers. */
  2395.     while ((buf = buf->b_next != NULL ? buf->b_next : firstbuf) != curbuf
  2396.         && ((flag == 'U'
  2397.             ? buf->b_p_bl
  2398.             : (!buf->b_p_bl
  2399.                 || (buf->b_ml.ml_mfp == NULL) != (flag == 'u')))
  2400.             || buf->b_scanned
  2401.             || (buf->b_ml.ml_mfp == NULL
  2402.             && ctrl_x_mode == CTRL_X_WHOLE_LINE)))
  2403.         ;
  2404.     return buf;
  2405. }
  2406.  
  2407. /*
  2408.  * Get the next expansion(s) for the text starting at the initial curbuf
  2409.  * position "ini" and in the direction dir.
  2410.  * Return the total of matches or -1 if still unknown -- Acevedo
  2411.  */
  2412.     static int
  2413. ins_compl_get_exp(ini, dir)
  2414.     pos_T    *ini;
  2415.     int        dir;
  2416. {
  2417.     static pos_T    first_match_pos;
  2418.     static pos_T    last_match_pos;
  2419.     static char_u    *e_cpt = (char_u *)"";    /* curr. entry in 'complete' */
  2420.     static int        found_all = FALSE;    /* Found all matches. */
  2421.     static buf_T    *ins_buf = NULL;
  2422.  
  2423.     pos_T        *pos;
  2424.     char_u        **matches;
  2425.     int            save_p_scs;
  2426.     int            save_p_ws;
  2427.     int            save_p_ic;
  2428.     int            i;
  2429.     int            num_matches;
  2430.     int            len;
  2431.     int            found_new_match;
  2432.     int            type = ctrl_x_mode;
  2433.     char_u        *ptr;
  2434.     char_u        *tmp_ptr;
  2435.     char_u        *dict = NULL;
  2436.     int            dict_f = 0;
  2437.     struct Completion    *old_match;
  2438.  
  2439.     if (!started_completion)
  2440.     {
  2441.     for (ins_buf = firstbuf; ins_buf != NULL; ins_buf = ins_buf->b_next)
  2442.         ins_buf->b_scanned = 0;
  2443.     found_all = FALSE;
  2444.     ins_buf = curbuf;
  2445.     e_cpt = continue_status & CONT_LOCAL ? (char_u *)"." : curbuf->b_p_cpt;
  2446.     last_match_pos = first_match_pos = *ini;
  2447.     }
  2448.  
  2449.     old_match = curr_match;        /* remember the last current match */
  2450.     pos = (dir == FORWARD) ? &last_match_pos : &first_match_pos;
  2451.     /* For ^N/^P loop over all the flags/windows/buffers in 'complete' */
  2452.     for (;;)
  2453.     {
  2454.     found_new_match = FAIL;
  2455.  
  2456.     /* For ^N/^P pick a new entry from e_cpt if started_completion is off,
  2457.      * or if found_all says this entry is done.  For ^X^L only use the
  2458.      * entries from 'complete' that look in loaded buffers. */
  2459.     if ((ctrl_x_mode == 0 || ctrl_x_mode == CTRL_X_WHOLE_LINE)
  2460.         && (!started_completion || found_all))
  2461.     {
  2462.         found_all = FALSE;
  2463.         while (*e_cpt == ',' || *e_cpt == ' ')
  2464.         e_cpt++;
  2465.         if (*e_cpt == '.' && !curbuf->b_scanned)
  2466.         {
  2467.         ins_buf = curbuf;
  2468.         first_match_pos = *ini;
  2469.         /* So that ^N can match word immediately after cursor */
  2470.         if (ctrl_x_mode == 0)
  2471.             dec(&first_match_pos);
  2472.         last_match_pos = first_match_pos;
  2473.         type = 0;
  2474.         }
  2475.         else if (vim_strchr((char_u *)"buwU", *e_cpt) != NULL
  2476.          && (ins_buf = ins_compl_next_buf(ins_buf, *e_cpt)) != curbuf)
  2477.         {
  2478.         /* Scan a buffer, but not the current one. */
  2479.         if (ins_buf->b_ml.ml_mfp != NULL)   /* loaded buffer */
  2480.         {
  2481.             started_completion = TRUE;
  2482.             first_match_pos.col = last_match_pos.col = 0;
  2483.             first_match_pos.lnum = ins_buf->b_ml.ml_line_count + 1;
  2484.             last_match_pos.lnum = 0;
  2485.             type = 0;
  2486.         }
  2487.         else    /* unloaded buffer, scan like dictionary */
  2488.         {
  2489.             found_all = TRUE;
  2490.             if (ins_buf->b_fname == NULL)
  2491.             continue;
  2492.             type = CTRL_X_DICTIONARY;
  2493.             dict = ins_buf->b_fname;
  2494.             dict_f = DICT_EXACT;
  2495.         }
  2496.         sprintf((char *)IObuff, _("Scanning: %s"),
  2497.             ins_buf->b_fname == NULL
  2498.                 ? buf_spname(ins_buf)
  2499.                 : ins_buf->b_sfname == NULL
  2500.                 ? (char *)ins_buf->b_fname
  2501.                 : (char *)ins_buf->b_sfname);
  2502.         msg_trunc_attr(IObuff, TRUE, hl_attr(HLF_R));
  2503.         }
  2504.         else if (*e_cpt == NUL)
  2505.         break;
  2506.         else
  2507.         {
  2508.         if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
  2509.             type = -1;
  2510.         else if (*e_cpt == 'k' || *e_cpt == 's')
  2511.         {
  2512.             if (*e_cpt == 'k')
  2513.             type = CTRL_X_DICTIONARY;
  2514.             else
  2515.             type = CTRL_X_THESAURUS;
  2516.             if (*++e_cpt != ',' && *e_cpt != NUL)
  2517.             {
  2518.             dict = e_cpt;
  2519.             dict_f = DICT_FIRST;
  2520.             }
  2521.         }
  2522. #ifdef FEAT_FIND_ID
  2523.         else if (*e_cpt == 'i')
  2524.             type = CTRL_X_PATH_PATTERNS;
  2525.         else if (*e_cpt == 'd')
  2526.             type = CTRL_X_PATH_DEFINES;
  2527. #endif
  2528.         else if (*e_cpt == ']' || *e_cpt == 't')
  2529.         {
  2530.             type = CTRL_X_TAGS;
  2531.             sprintf((char*)IObuff, _("Scanning tags."));
  2532.             msg_trunc_attr(IObuff, TRUE, hl_attr(HLF_R));
  2533.         }
  2534.         else
  2535.             type = -1;
  2536.  
  2537.         /* in any case e_cpt is advanced to the next entry */
  2538.         (void)copy_option_part(&e_cpt, IObuff, IOSIZE, ",");
  2539.  
  2540.         found_all = TRUE;
  2541.         if (type == -1)
  2542.             continue;
  2543.         }
  2544.     }
  2545.  
  2546.     switch (type)
  2547.     {
  2548.     case -1:
  2549.         break;
  2550. #ifdef FEAT_FIND_ID
  2551.     case CTRL_X_PATH_PATTERNS:
  2552.     case CTRL_X_PATH_DEFINES:
  2553.         find_pattern_in_path(complete_pat, dir,
  2554.                  (int)STRLEN(complete_pat), FALSE, FALSE,
  2555.                  (type == CTRL_X_PATH_DEFINES
  2556.                   && !(continue_status & CONT_SOL))
  2557.                  ? FIND_DEFINE : FIND_ANY, 1L, ACTION_EXPAND,
  2558.                  (linenr_T)1, (linenr_T)MAXLNUM);
  2559.         break;
  2560. #endif
  2561.  
  2562.     case CTRL_X_DICTIONARY:
  2563.     case CTRL_X_THESAURUS:
  2564.         ins_compl_dictionaries(
  2565.             dict ? dict
  2566.              : (type == CTRL_X_THESAURUS
  2567.                  ? (*curbuf->b_p_tsr == NUL
  2568.                  ? p_tsr
  2569.                  : curbuf->b_p_tsr)
  2570.                  : (*curbuf->b_p_dict == NUL
  2571.                  ? p_dict
  2572.                  : curbuf->b_p_dict)),
  2573.                 complete_pat, dir,
  2574.                  dict ? dict_f : 0, type == CTRL_X_THESAURUS);
  2575.         dict = NULL;
  2576.         break;
  2577.  
  2578.     case CTRL_X_TAGS:
  2579.         /* set p_ic according to p_ic, p_scs and pat for find_tags(). */
  2580.         save_p_ic = p_ic;
  2581.         p_ic = ignorecase(complete_pat);
  2582.  
  2583.         /* Find up to TAG_MANY matches.  Avoids that an enourmous number
  2584.          * of matches is found when complete_pat is empty */
  2585.         if (find_tags(complete_pat, &num_matches, &matches,
  2586.             TAG_REGEXP | TAG_NAMES | TAG_NOIC |
  2587.             TAG_INS_COMP | (ctrl_x_mode ? TAG_VERBOSE : 0),
  2588.             TAG_MANY) == OK && num_matches > 0)
  2589.         {
  2590.         ins_compl_add_matches(num_matches, matches, dir);
  2591.         }
  2592.         p_ic = save_p_ic;
  2593.         break;
  2594.  
  2595.     case CTRL_X_FILES:
  2596.         if (expand_wildcards(1, &complete_pat, &num_matches, &matches,
  2597.                   EW_FILE|EW_DIR|EW_ADDSLASH|EW_SILENT) == OK)
  2598.         {
  2599.  
  2600.         /* May change home directory back to "~". */
  2601.         tilde_replace(complete_pat, num_matches, matches);
  2602.         ins_compl_add_matches(num_matches, matches, dir);
  2603.         }
  2604.         break;
  2605.  
  2606.     case CTRL_X_CMDLINE:
  2607.         if (expand_cmdline(&complete_xp, complete_pat,
  2608.             (int)STRLEN(complete_pat),
  2609.                      &num_matches, &matches) == EXPAND_OK)
  2610.         ins_compl_add_matches(num_matches, matches, dir);
  2611.         break;
  2612.  
  2613.     default:    /* normal ^P/^N and ^X^L */
  2614.         /*
  2615.          * If 'infercase' is set, don't use 'smartcase' here
  2616.          */
  2617.         save_p_scs = p_scs;
  2618.         if (ins_buf->b_p_inf)
  2619.         p_scs = FALSE;
  2620.         /*    buffers other than curbuf are scanned from the beginning or the
  2621.          *    end but never from the middle, thus setting nowrapscan in this
  2622.          *    buffers is a good idea, on the other hand, we always set
  2623.          *    wrapscan for curbuf to avoid missing matches -- Acevedo,Webb */
  2624.         save_p_ws = p_ws;
  2625.         if (ins_buf != curbuf)
  2626.         p_ws = FALSE;
  2627.         else if (*e_cpt == '.')
  2628.         p_ws = TRUE;
  2629.         for (;;)
  2630.         {
  2631.         int    reuse = 0;
  2632.  
  2633.         /* ctrl_x_mode == CTRL_X_WHOLE_LINE || word-wise search that has
  2634.          * added a word that was at the beginning of the line */
  2635.         if (    ctrl_x_mode == CTRL_X_WHOLE_LINE
  2636.             || (continue_status & CONT_SOL))
  2637.             found_new_match = search_for_exact_line(ins_buf, pos,
  2638.                                 dir, complete_pat);
  2639.         else
  2640.             found_new_match = searchit(NULL, ins_buf, pos, dir,
  2641.                  complete_pat, 1L, SEARCH_KEEP + SEARCH_NFMSG,
  2642.                                      RE_LAST);
  2643.         if (!started_completion)
  2644.         {
  2645.             /* set started_completion even on fail */
  2646.             started_completion = TRUE;
  2647.             first_match_pos = *pos;
  2648.             last_match_pos = *pos;
  2649.         }
  2650.         else if (first_match_pos.lnum == last_match_pos.lnum
  2651.              && first_match_pos.col == last_match_pos.col)
  2652.             found_new_match = FAIL;
  2653.         if (found_new_match == FAIL)
  2654.         {
  2655.             if (ins_buf == curbuf)
  2656.             found_all = TRUE;
  2657.             break;
  2658.         }
  2659.  
  2660.         /* when ADDING, the text before the cursor matches, skip it */
  2661.         if (    (continue_status & CONT_ADDING) && ins_buf == curbuf
  2662.             && ini->lnum == pos->lnum
  2663.             && ini->col  == pos->col)
  2664.             continue;
  2665.         ptr = ml_get_buf(ins_buf, pos->lnum, FALSE) + pos->col;
  2666.         if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
  2667.         {
  2668.             if (continue_status & CONT_ADDING)
  2669.             {
  2670.             if (pos->lnum >= ins_buf->b_ml.ml_line_count)
  2671.                 continue;
  2672.             ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE);
  2673.             if (!p_paste)
  2674.                 ptr = skipwhite(ptr);
  2675.             }
  2676.             len = (int)STRLEN(ptr);
  2677.         }
  2678.         else
  2679.         {
  2680.             tmp_ptr = ptr;
  2681.             if (continue_status & CONT_ADDING)
  2682.             {
  2683.             tmp_ptr += completion_length;
  2684.             /* Skip if already inside a word. */
  2685.             if (vim_iswordp(tmp_ptr))
  2686.                 continue;
  2687.             /* Find start of next word. */
  2688.             tmp_ptr = find_word_start(tmp_ptr);
  2689.             }
  2690.             /* Find end of this word. */
  2691.             tmp_ptr = find_word_end(tmp_ptr);
  2692.             len = (int)(tmp_ptr - ptr);
  2693.  
  2694.             if ((continue_status & CONT_ADDING)
  2695.                           && len == completion_length)
  2696.             {
  2697.             if (pos->lnum < ins_buf->b_ml.ml_line_count)
  2698.             {
  2699.                 /* Try next line, if any. the new word will be
  2700.                  * "join" as if the normal command "J" was used.
  2701.                  * IOSIZE is always greater than
  2702.                  * completion_length, so the next STRNCPY always
  2703.                  * works -- Acevedo */
  2704.                 STRNCPY(IObuff, ptr, len);
  2705.                 ptr = ml_get_buf(ins_buf, pos->lnum + 1, FALSE);
  2706.                 tmp_ptr = ptr = skipwhite(ptr);
  2707.                 /* Find start of next word. */
  2708.                 tmp_ptr = find_word_start(tmp_ptr);
  2709.                 /* Find end of next word. */
  2710.                 tmp_ptr = find_word_end(tmp_ptr);
  2711.                 if (tmp_ptr > ptr)
  2712.                 {
  2713.                 if (*ptr != ')' && IObuff[len-1] != TAB)
  2714.                 {
  2715.                     if (IObuff[len-1] != ' ')
  2716.                     IObuff[len++] = ' ';
  2717.                     /* IObuf =~ "\k.* ", thus len >= 2 */
  2718.                     if (p_js
  2719.                     && (IObuff[len-2] == '.'
  2720.                         || (vim_strchr(p_cpo, CPO_JOINSP)
  2721.                                        == NULL
  2722.                         && (IObuff[len-2] == '?'
  2723.                             || IObuff[len-2] == '!'))))
  2724.                     IObuff[len++] = ' ';
  2725.                 }
  2726.                 /* copy as much as posible of the new word */
  2727.                 if (tmp_ptr - ptr >= IOSIZE - len)
  2728.                     tmp_ptr = ptr + IOSIZE - len - 1;
  2729.                 STRNCPY(IObuff + len, ptr, tmp_ptr - ptr);
  2730.                 len += (int)(tmp_ptr - ptr);
  2731.                 reuse |= CONT_S_IPOS;
  2732.                 }
  2733.                 IObuff[len] = NUL;
  2734.                 ptr = IObuff;
  2735.             }
  2736.             if (len == completion_length)
  2737.                 continue;
  2738.             }
  2739.         }
  2740.         if (ins_compl_add_infercase(ptr, len,
  2741.                 ins_buf == curbuf ?  NULL : ins_buf->b_sfname,
  2742.                               dir, reuse) != FAIL)
  2743.         {
  2744.             found_new_match = OK;
  2745.             break;
  2746.         }
  2747.         }
  2748.         p_scs = save_p_scs;
  2749.         p_ws = save_p_ws;
  2750.     }
  2751.     /* check if curr_match has changed, (e.g. other type of expansion
  2752.      * added somenthing) */
  2753.     if (curr_match != old_match)
  2754.         found_new_match = OK;
  2755.  
  2756.     /* break the loop for specialized modes (use 'complete' just for the
  2757.      * generic ctrl_x_mode == 0) or when we've found a new match */
  2758.     if ((ctrl_x_mode != 0 && ctrl_x_mode != CTRL_X_WHOLE_LINE)
  2759.         || found_new_match != FAIL)
  2760.         break;
  2761.  
  2762.     /* Mark a buffer scanned when it has been scanned completely */
  2763.     if (type == 0 || type == CTRL_X_PATH_PATTERNS)
  2764.         ins_buf->b_scanned = TRUE;
  2765.  
  2766.     started_completion = FALSE;
  2767.     }
  2768.     started_completion = TRUE;
  2769.  
  2770.     if ((ctrl_x_mode == 0 || ctrl_x_mode == CTRL_X_WHOLE_LINE)
  2771.         && *e_cpt == NUL)        /* Got to end of 'complete' */
  2772.     found_new_match = FAIL;
  2773.  
  2774.     i = -1;        /* total of matches, unknown */
  2775.     if (found_new_match == FAIL
  2776.         || (ctrl_x_mode != 0 && ctrl_x_mode != CTRL_X_WHOLE_LINE))
  2777.     i = ins_compl_make_cyclic();
  2778.  
  2779.     /* If several matches were added (FORWARD) or the search failed and has
  2780.      * just been made cyclic then we have to move curr_match to the next or
  2781.      * previous entry (if any) -- Acevedo */
  2782.     curr_match = dir == FORWARD ? old_match->next : old_match->prev;
  2783.     if (curr_match == NULL)
  2784.     curr_match = old_match;
  2785.     return i;
  2786. }
  2787.  
  2788. /* Delete the old text being completed. */
  2789.     static void
  2790. ins_compl_delete()
  2791. {
  2792.     int        i;
  2793.  
  2794.     /*
  2795.      * In insert mode: Delete the typed part.
  2796.      * In replace mode: Put the old characters back, if any.
  2797.      */
  2798.     i = complete_col + (continue_status & CONT_ADDING ? completion_length : 0);
  2799.     backspace_until_column(i);
  2800.     changed_cline_bef_curs();
  2801. }
  2802.  
  2803. /* Insert the new text being completed. */
  2804.     static void
  2805. ins_compl_insert()
  2806. {
  2807.     ins_bytes(shown_match->str + curwin->w_cursor.col - complete_col);
  2808. }
  2809.  
  2810. /*
  2811.  * Fill in the next completion in the current direction.
  2812.  * If allow_get_expansion is TRUE, then we may call ins_compl_get_exp() to get
  2813.  * more completions.  If it is FALSE, then we just do nothing when there are
  2814.  * no more completions in a given direction.  The latter case is used when we
  2815.  * are still in the middle of finding completions, to allow browsing through
  2816.  * the ones found so far.
  2817.  * Return the total number of matches, or -1 if still unknown -- webb.
  2818.  *
  2819.  * curr_match is currently being used by ins_compl_get_exp(), so we use
  2820.  * shown_match here.
  2821.  *
  2822.  * Note that this function may be called recursively once only.  First with
  2823.  * allow_get_expansion TRUE, which calls ins_compl_get_exp(), which in turn
  2824.  * calls this function with allow_get_expansion FALSE.
  2825.  */
  2826.     static int
  2827. ins_compl_next(allow_get_expansion)
  2828.     int        allow_get_expansion;
  2829. {
  2830.     int        num_matches = -1;
  2831.     int        i;
  2832.  
  2833.     if (allow_get_expansion)
  2834.     {
  2835.     /* Delete old text to be replaced */
  2836.     ins_compl_delete();
  2837.     }
  2838.     completion_pending = FALSE;
  2839.     if (shown_direction == FORWARD && shown_match->next != NULL)
  2840.     shown_match = shown_match->next;
  2841.     else if (shown_direction == BACKWARD && shown_match->prev != NULL)
  2842.     shown_match = shown_match->prev;
  2843.     else
  2844.     {
  2845.     completion_pending = TRUE;
  2846.     if (allow_get_expansion)
  2847.     {
  2848.         num_matches = ins_compl_get_exp(&initial_pos, complete_direction);
  2849.         if (completion_pending)
  2850.         {
  2851.         if (complete_direction == shown_direction)
  2852.             shown_match = curr_match;
  2853.         }
  2854.     }
  2855.     else
  2856.         return -1;
  2857.     }
  2858.  
  2859.     /* Insert the text of the new completion */
  2860.     ins_compl_insert();
  2861.  
  2862.     if (!allow_get_expansion)
  2863.     {
  2864.     /* Display the current match. */
  2865.     update_screen(0);
  2866.  
  2867.     /* Delete old text to be replaced, since we're still searching and
  2868.      * don't want to match ourselves!  */
  2869.     ins_compl_delete();
  2870.     }
  2871.  
  2872.     /*
  2873.      * Show the file name for the match (if any)
  2874.      * Truncate the file name to avoid a wait for return.
  2875.      */
  2876.     if (shown_match->fname != NULL)
  2877.     {
  2878.     STRCPY(IObuff, "match in file ");
  2879.     i = (vim_strsize(shown_match->fname) + 16) - sc_col;
  2880.     if (i <= 0)
  2881.         i = 0;
  2882.     else
  2883.         STRCAT(IObuff, "<");
  2884.     STRCAT(IObuff, shown_match->fname + i);
  2885.     msg(IObuff);
  2886.     redraw_cmdline = FALSE;        /* don't overwrite! */
  2887.     }
  2888.  
  2889.     return num_matches;
  2890. }
  2891.  
  2892. /*
  2893.  * Call this while finding completions, to check whether the user has hit a key
  2894.  * that should change the currently displayed completion, or exit completion
  2895.  * mode.  Also, when completion_pending is TRUE, show a completion as soon as
  2896.  * possible. -- webb
  2897.  */
  2898.     void
  2899. ins_compl_check_keys()
  2900. {
  2901.     static int    count = 0;
  2902.  
  2903.     int        c;
  2904.  
  2905.     /* Don't check when reading keys from a script.  That would break the test
  2906.      * scripts */
  2907.     if (using_script())
  2908.     return;
  2909.  
  2910.     /* Only do this at regular intervals */
  2911.     if (++count < CHECK_KEYS_TIME)
  2912.     return;
  2913.     count = 0;
  2914.  
  2915.     c = vpeekc_any();
  2916.     if (c != NUL)
  2917.     {
  2918.     if (vim_is_ctrl_x_key(c) && c != Ctrl_X && c != Ctrl_R)
  2919.     {
  2920.         c = safe_vgetc();    /* Eat the character */
  2921.         if (c == Ctrl_P || c == Ctrl_L)
  2922.         shown_direction = BACKWARD;
  2923.         else
  2924.         shown_direction = FORWARD;
  2925.         (void)ins_compl_next(FALSE);
  2926.     }
  2927.     else if (c != Ctrl_R)
  2928.         completion_interrupted = TRUE;
  2929.     }
  2930.     if (completion_pending && !got_int)
  2931.     (void)ins_compl_next(FALSE);
  2932. }
  2933.  
  2934. /*
  2935.  * Do Insert mode completion.
  2936.  * Called when character "c" was typed, which has a meaning for completion.
  2937.  * Returns OK if completion was done, FAIL if something failed (out of mem).
  2938.  */
  2939.     static int
  2940. ins_complete(c)
  2941.     int            c;
  2942. {
  2943.     char_u        *line;
  2944.     char_u        *tmp_ptr = NULL;        /* init for gcc */
  2945.     int            temp = 0;
  2946.  
  2947.     if (c == Ctrl_P || c == Ctrl_L)
  2948.     complete_direction = BACKWARD;
  2949.     else
  2950.     complete_direction = FORWARD;
  2951.     if (!started_completion)
  2952.     {
  2953.     /* First time we hit ^N or ^P (in a row, I mean) */
  2954.  
  2955.     /* Turn off 'sm' so we don't show matches with ^X^L */
  2956.     save_sm = p_sm;
  2957.     p_sm = FALSE;
  2958.  
  2959.     did_ai = FALSE;
  2960. #ifdef FEAT_SMARTINDENT
  2961.     did_si = FALSE;
  2962.     can_si = FALSE;
  2963.     can_si_back = FALSE;
  2964. #endif
  2965.     if (stop_arrow() == FAIL)
  2966.         return FAIL;
  2967.  
  2968.     line = ml_get(curwin->w_cursor.lnum);
  2969.     complete_col = curwin->w_cursor.col;
  2970.  
  2971.     /* if this same ctrl_x_mode has been interrupted use the text from
  2972.      * "initial_pos" to the cursor as a pattern to add a new word instead
  2973.      * of expand the one before the cursor, in word-wise if "initial_pos"
  2974.      * is not in the same line as the cursor then fix it (the line has
  2975.      * been split because it was longer than 'tw').  if SOL is set then
  2976.      * skip the previous pattern, a word at the beginning of the line has
  2977.      * been inserted, we'll look for that  -- Acevedo. */
  2978.     if ((continue_status & CONT_INTRPT) && continue_mode == ctrl_x_mode)
  2979.     {
  2980.         /*
  2981.          * it is a continued search
  2982.          */
  2983.         continue_status &= ~CONT_INTRPT;    /* remove INTRPT */
  2984.         if (ctrl_x_mode == 0 || ctrl_x_mode == CTRL_X_PATH_PATTERNS
  2985.                     || ctrl_x_mode == CTRL_X_PATH_DEFINES)
  2986.         {
  2987.         if (initial_pos.lnum != curwin->w_cursor.lnum)
  2988.         {
  2989.             /* line (probably) wrapped, set initial_pos to the first
  2990.              * non_blank in the line, if it is not a wordchar include
  2991.              * it to get a better pattern, but then we don't want the
  2992.              * "\\<" prefix, check it bellow */
  2993.             tmp_ptr = skipwhite(line);
  2994.             initial_pos.col = (colnr_T) (tmp_ptr - line);
  2995.             initial_pos.lnum = curwin->w_cursor.lnum;
  2996.             continue_status &= ~CONT_SOL;    /* clear SOL if present */
  2997.         }
  2998.         else
  2999.         {
  3000.             /* S_IPOS was set when we inserted a word that was at the
  3001.              * beginning of the line, which means that we'll go to SOL
  3002.              * mode but first we need to redefine initial_pos */
  3003.             if (continue_status & CONT_S_IPOS)
  3004.             {
  3005.             continue_status |= CONT_SOL;
  3006.             initial_pos.col = (colnr_T) (skipwhite(line + completion_length +
  3007.                             initial_pos.col) - line);
  3008.             }
  3009.             tmp_ptr = line + initial_pos.col;
  3010.         }
  3011.         temp = curwin->w_cursor.col - (int)(tmp_ptr - line);
  3012.         /* IObuf is used to add a "word from the next line" would we
  3013.          * have enough space?  just being paranoic */
  3014. #define    MIN_SPACE 75
  3015.         if (temp > (IOSIZE - MIN_SPACE))
  3016.         {
  3017.             continue_status &= ~CONT_SOL;
  3018.             temp = (IOSIZE - MIN_SPACE);
  3019.             tmp_ptr = line + curwin->w_cursor.col - temp;
  3020.         }
  3021.         continue_status |= CONT_ADDING | CONT_N_ADDS;
  3022.         if (temp < 1)
  3023.             continue_status &= CONT_LOCAL;
  3024.         }
  3025.         else if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
  3026.         continue_status = CONT_ADDING | CONT_N_ADDS;
  3027.         else
  3028.         continue_status = 0;
  3029.     }
  3030.     else
  3031.         continue_status &= CONT_LOCAL;
  3032.  
  3033.     if (!(continue_status & CONT_ADDING))    /* normal expansion */
  3034.     {
  3035.         continue_mode = ctrl_x_mode;
  3036.         if (ctrl_x_mode != 0)    /* Remove LOCAL if ctrl_x_mode != 0 */
  3037.         continue_status = 0;
  3038.         continue_status |= CONT_N_ADDS;
  3039.         initial_pos = curwin->w_cursor;
  3040.         temp = (int)complete_col;
  3041.         tmp_ptr = line;
  3042.     }
  3043.  
  3044.     /* Work out completion pattern and original text -- webb */
  3045.     if (ctrl_x_mode == 0 || (ctrl_x_mode & CTRL_X_WANT_IDENT))
  3046.     {
  3047.         if (       (continue_status & CONT_SOL)
  3048.             || ctrl_x_mode == CTRL_X_PATH_DEFINES)
  3049.         {
  3050.         if (!(continue_status & CONT_ADDING))
  3051.         {
  3052.             while (--temp >= 0 && vim_isIDc(line[temp]))
  3053.             ;
  3054.             tmp_ptr += ++temp;
  3055.             temp = complete_col - temp;
  3056.         }
  3057.         complete_pat = vim_strnsave(tmp_ptr, temp);
  3058.         if (complete_pat == NULL)
  3059.             return FAIL;
  3060.         if (p_ic)
  3061.             str_foldcase(complete_pat);
  3062.         }
  3063.         else if (continue_status & CONT_ADDING)
  3064.         {
  3065.         char_u        *prefix = (char_u *)"\\<";
  3066.  
  3067.         /* we need 3 extra chars, 1 for the NUL and
  3068.          * 2 >= strlen(prefix)    -- Acevedo */
  3069.         complete_pat = alloc(quote_meta(NULL, tmp_ptr, temp) + 3);
  3070.         if (complete_pat == NULL)
  3071.             return FAIL;
  3072.         if (!vim_iswordp(tmp_ptr)
  3073.             || (tmp_ptr > line
  3074.                 && (
  3075. #ifdef FEAT_MBYTE
  3076.                 vim_iswordp(mb_prevptr(line, tmp_ptr))
  3077. #else
  3078.                 vim_iswordc(*(tmp_ptr - 1))
  3079. #endif
  3080.                 )))
  3081.             prefix = (char_u *)"";
  3082.         STRCPY((char *)complete_pat, prefix);
  3083.         (void)quote_meta(complete_pat + STRLEN(prefix), tmp_ptr, temp);
  3084.         }
  3085.         else if (
  3086. #ifdef FEAT_MBYTE
  3087.             --temp < 0 || !vim_iswordp(mb_prevptr(line,
  3088.                                  line + temp + 1))
  3089. #else
  3090.             --temp < 0 || !vim_iswordc(line[temp])
  3091. #endif
  3092.             )
  3093.         {
  3094.         /* Match any word of at least two chars */
  3095.         complete_pat = vim_strsave((char_u *)"\\<\\k\\k");
  3096.         if (complete_pat == NULL)
  3097.             return FAIL;
  3098.         tmp_ptr += complete_col;
  3099.         temp = 0;
  3100.         }
  3101.         else
  3102.         {
  3103. #ifdef FEAT_MBYTE
  3104.         /* Search the point of change class of multibyte character
  3105.          * or not a word single byte character backward.  */
  3106.         if (has_mbyte)
  3107.         {
  3108.             int base_class;
  3109.             int head_off;
  3110.  
  3111.             temp -= (*mb_head_off)(line, line + temp);
  3112.             base_class = mb_get_class(line + temp);
  3113.             while (--temp >= 0)
  3114.             {
  3115.             head_off = (*mb_head_off)(line, line + temp);
  3116.             if (base_class != mb_get_class(line + temp - head_off))
  3117.                 break;
  3118.             temp -= head_off;
  3119.             }
  3120.         }
  3121.         else
  3122. #endif
  3123.             while (--temp >= 0 && vim_iswordc(line[temp]))
  3124.             ;
  3125.         tmp_ptr += ++temp;
  3126.         if ((temp = (int)complete_col - temp) == 1)
  3127.         {
  3128.             /* Only match word with at least two chars -- webb
  3129.              * there's no need to call quote_meta,
  3130.              * alloc(7) is enough  -- Acevedo
  3131.              */
  3132.             complete_pat = alloc(7);
  3133.             if (complete_pat == NULL)
  3134.             return FAIL;
  3135.             STRCPY((char *)complete_pat, "\\<");
  3136.             (void)quote_meta(complete_pat + 2, tmp_ptr, 1);
  3137.             STRCAT((char *)complete_pat, "\\k");
  3138.         }
  3139.         else
  3140.         {
  3141.             complete_pat = alloc(quote_meta(NULL, tmp_ptr, temp) + 3);
  3142.             if (complete_pat == NULL)
  3143.             return FAIL;
  3144.             STRCPY((char *)complete_pat, "\\<");
  3145.             (void)quote_meta(complete_pat + 2, tmp_ptr, temp);
  3146.         }
  3147.         }
  3148.     }
  3149.     else if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
  3150.     {
  3151.         tmp_ptr = skipwhite(line);
  3152.         temp = (int)complete_col - (int)(tmp_ptr - line);
  3153.         if (temp < 0)    /* cursor in indent: empty pattern */
  3154.         temp = 0;
  3155.         complete_pat = vim_strnsave(tmp_ptr, temp);
  3156.         if (complete_pat == NULL)
  3157.         return FAIL;
  3158.         if (p_ic)
  3159.         str_foldcase(complete_pat);
  3160.     }
  3161.     else if (ctrl_x_mode == CTRL_X_FILES)
  3162.     {
  3163.         while (--temp >= 0 && vim_isfilec(line[temp]))
  3164.         ;
  3165.         tmp_ptr += ++temp;
  3166.         temp = (int)complete_col - temp;
  3167.         complete_pat = addstar(tmp_ptr, temp, EXPAND_FILES);
  3168.         if (complete_pat == NULL)
  3169.         return FAIL;
  3170.     }
  3171.     else if (ctrl_x_mode == CTRL_X_CMDLINE)
  3172.     {
  3173.         complete_pat = vim_strnsave(line, complete_col);
  3174.         if (complete_pat == NULL)
  3175.         return FAIL;
  3176.         set_cmd_context(&complete_xp, complete_pat,
  3177.                      (int)STRLEN(complete_pat), complete_col);
  3178.         if (complete_xp.xp_context == EXPAND_UNSUCCESSFUL
  3179.             || complete_xp.xp_context == EXPAND_NOTHING)
  3180.         return FAIL;
  3181.         temp = (int)(complete_xp.xp_pattern - complete_pat);
  3182.         tmp_ptr = line + temp;
  3183.         temp = complete_col - temp;
  3184.     }
  3185.     complete_col = (colnr_T) (tmp_ptr - line);
  3186.  
  3187.     if (continue_status & CONT_ADDING)
  3188.     {
  3189.         edit_submode_pre = (char_u *)_(" Adding");
  3190.         if (ctrl_x_mode == CTRL_X_WHOLE_LINE)
  3191.         {
  3192.         /* Insert a new line, keep indentation but ignore 'comments' */
  3193. #ifdef FEAT_COMMENTS
  3194.         char_u *old = curbuf->b_p_com;
  3195.  
  3196.         curbuf->b_p_com = (char_u *)"";
  3197. #endif
  3198.         initial_pos.lnum = curwin->w_cursor.lnum;
  3199.         initial_pos.col = complete_col;
  3200.         ins_eol('\r');
  3201. #ifdef FEAT_COMMENTS
  3202.         curbuf->b_p_com = old;
  3203. #endif
  3204.         tmp_ptr = (char_u *)"";
  3205.         temp = 0;
  3206.         complete_col = curwin->w_cursor.col;
  3207.         }
  3208.     }
  3209.     else
  3210.     {
  3211.         edit_submode_pre = NULL;
  3212.         initial_pos.col = complete_col;
  3213.     }
  3214.  
  3215.     if (continue_status & CONT_LOCAL)
  3216.         edit_submode = (char_u *)_(ctrl_x_msgs[2]);
  3217.     else
  3218.         edit_submode = (char_u *)_(CTRL_X_MSG(ctrl_x_mode));
  3219.  
  3220.     completion_length = temp;
  3221.  
  3222.     /* Always add completion for the original text.  Note that
  3223.      * "original_text" itself (not a copy) is added, it will be freed when
  3224.      * the list of matches is freed. */
  3225.     if ((original_text = vim_strnsave(tmp_ptr, temp)) == NULL
  3226.         || ins_compl_add(original_text, -1, NULL, 0, ORIGINAL_TEXT) != OK)
  3227.     {
  3228.         vim_free(complete_pat);
  3229.         complete_pat = NULL;
  3230.         vim_free(original_text);
  3231.         return FAIL;
  3232.     }
  3233.  
  3234.     /* showmode might reset the internal line pointers, so it must
  3235.      * be called before line = ml_get(), or when this address is no
  3236.      * longer needed.  -- Acevedo.
  3237.      */
  3238.     edit_submode_extra = (char_u *)_("-- Searching...");
  3239.     edit_submode_highl = HLF_COUNT;
  3240.     showmode();
  3241.     edit_submode_extra = NULL;
  3242.     out_flush();
  3243.     }
  3244.  
  3245.     shown_match = curr_match;
  3246.     shown_direction = complete_direction;
  3247.  
  3248.     /*
  3249.      * Find next match.
  3250.      */
  3251.     temp = ins_compl_next(TRUE);
  3252.  
  3253.     if (temp > 1)    /* all matches have been found */
  3254.     completion_matches = temp;
  3255.     curr_match = shown_match;
  3256.     complete_direction = shown_direction;
  3257.     completion_interrupted = FALSE;
  3258.  
  3259.     /* eat the ESC to avoid leaving insert mode */
  3260.     if (got_int && !global_busy)
  3261.     {
  3262.     (void)vgetc();
  3263.     got_int = FALSE;
  3264.     }
  3265.  
  3266.     /* we found no match if the list has only the original_text-entry */
  3267.     if (first_match == first_match->next)
  3268.     {
  3269.     edit_submode_extra = (continue_status & CONT_ADDING)
  3270.             && completion_length > 1
  3271.                  ? (char_u *)_(e_hitend) : (char_u *)_(e_patnotf);
  3272.     edit_submode_highl = HLF_E;
  3273.     /* remove N_ADDS flag, so next ^X<> won't try to go to ADDING mode,
  3274.      * because we couldn't expand anything at first place, but if we used
  3275.      * ^P, ^N, ^X^I or ^X^D we might want to add-expand a single-char-word
  3276.      * (such as M in M'exico) if not tried already.  -- Acevedo */
  3277.     if (       completion_length > 1
  3278.         || (continue_status & CONT_ADDING)
  3279.         || (ctrl_x_mode != 0
  3280.             && ctrl_x_mode != CTRL_X_PATH_PATTERNS
  3281.             && ctrl_x_mode != CTRL_X_PATH_DEFINES))
  3282.         continue_status &= ~CONT_N_ADDS;
  3283.     }
  3284.  
  3285.     if (curr_match->original & CONT_S_IPOS)
  3286.     continue_status |= CONT_S_IPOS;
  3287.     else
  3288.     continue_status &= ~CONT_S_IPOS;
  3289.  
  3290.     if (edit_submode_extra == NULL)
  3291.     {
  3292.     if (curr_match->original & ORIGINAL_TEXT)
  3293.     {
  3294.         edit_submode_extra = (char_u *)_("Back at original");
  3295.         edit_submode_highl = HLF_W;
  3296.     }
  3297.     else if (continue_status & CONT_S_IPOS)
  3298.     {
  3299.         edit_submode_extra = (char_u *)_("Word from other line");
  3300.         edit_submode_highl = HLF_COUNT;
  3301.     }
  3302.     else if (curr_match->next == curr_match->prev)
  3303.     {
  3304.         edit_submode_extra = (char_u *)_("The only match");
  3305.         edit_submode_highl = HLF_COUNT;
  3306.     }
  3307.     else
  3308.     {
  3309.         /* Update completion sequence number when needed. */
  3310.         if (curr_match->number == -1)
  3311.         {
  3312.         int            number = 0;
  3313.         struct Completion   *match;
  3314.  
  3315.         if (complete_direction == FORWARD)
  3316.         {
  3317.             /* search backwards for the first valid (!= -1) number.
  3318.              * This should normally succeed already at the first loop
  3319.              * cycle, so it's fast! */
  3320.             for (match = curr_match->prev; match != NULL
  3321.                  && match != first_match; match = match->prev)
  3322.             if (match->number != -1)
  3323.             {
  3324.                 number = match->number;
  3325.                 break;
  3326.             }
  3327.             if (match != NULL)
  3328.             /* go up and assign all numbers which are not assigned
  3329.              * yet */
  3330.             for (match = match->next; match
  3331.                   && match->number == -1; match = match->next)
  3332.                 match->number = ++number;
  3333.         }
  3334.         else /* BACKWARD */
  3335.         {
  3336.             /* search forwards (upwards) for the first valid (!= -1)
  3337.              * number.  This should normally succeed already at the
  3338.              * first loop cycle, so it's fast! */
  3339.             for (match = curr_match->next; match != NULL
  3340.                  && match != first_match; match = match->next)
  3341.             if (match->number != -1)
  3342.             {
  3343.                 number = match->number;
  3344.                 break;
  3345.             }
  3346.             if (match != NULL)
  3347.             /* go down and assign all numbers which are not
  3348.              * assigned yet */
  3349.             for (match = match->prev; match
  3350.                   && match->number == -1; match = match->prev)
  3351.                 match->number = ++number;
  3352.         }
  3353.         }
  3354.  
  3355.         /* The match should always have a sequnce number now, this is just
  3356.          * a safety check. */
  3357.         if (curr_match->number != -1)
  3358.         {
  3359.         /* Space for 10 text chars. + 2x10-digit no.s */
  3360.         static char_u match_ref[31];
  3361.  
  3362.         if (completion_matches > 0)
  3363.             sprintf((char *)IObuff, _("match %d of %d"),
  3364.                       curr_match->number, completion_matches);
  3365.         else
  3366.             sprintf((char *)IObuff, _("match %d"), curr_match->number);
  3367.         STRNCPY(match_ref, IObuff, 30 );
  3368.         match_ref[30] = '\0';
  3369.         edit_submode_extra = match_ref;
  3370.         edit_submode_highl = HLF_R;
  3371.         if (dollar_vcol)
  3372.             curs_columns(FALSE);
  3373.         }
  3374.     }
  3375.     }
  3376.  
  3377.     /* Show a message about what (completion) mode we're in. */
  3378.     showmode();
  3379.     if (edit_submode_extra != NULL)
  3380.     {
  3381.     if (!p_smd)
  3382.         msg_attr(edit_submode_extra,
  3383.             edit_submode_highl < HLF_COUNT
  3384.             ? hl_attr(edit_submode_highl) : 0);
  3385.     }
  3386.     else
  3387.     msg_clr_cmdline();    /* necessary for "noshowmode" */
  3388.  
  3389.     return OK;
  3390. }
  3391.  
  3392. /*
  3393.  * Looks in the first "len" chars. of "src" for search-metachars.
  3394.  * If dest is not NULL the chars. are copied there quoting (with
  3395.  * a backslash) the metachars, and dest would be NUL terminated.
  3396.  * Returns the length (needed) of dest
  3397.  */
  3398.     static int
  3399. quote_meta(dest, src, len)
  3400.     char_u    *dest;
  3401.     char_u    *src;
  3402.     int        len;
  3403. {
  3404.     int    m;
  3405.  
  3406.     for (m = len; --len >= 0; src++)
  3407.     {
  3408.     switch (*src)
  3409.     {
  3410.         case '.':
  3411.         case '*':
  3412.         case '[':
  3413.         if (ctrl_x_mode == CTRL_X_DICTIONARY
  3414.                        || ctrl_x_mode == CTRL_X_THESAURUS)
  3415.             break;
  3416.         case '~':
  3417.         if (!p_magic)    /* quote these only if magic is set */
  3418.             break;
  3419.         case '\\':
  3420.         if (ctrl_x_mode == CTRL_X_DICTIONARY
  3421.                        || ctrl_x_mode == CTRL_X_THESAURUS)
  3422.             break;
  3423.         case '^':        /* currently it's not needed. */
  3424.         case '$':
  3425.         m++;
  3426.         if (dest != NULL)
  3427.             *dest++ = '\\';
  3428.         break;
  3429.     }
  3430.     if (dest != NULL)
  3431.         *dest++ = *src;
  3432. #ifdef FEAT_MBYTE
  3433.     /* Copy remaining bytes of a multibyte character. */
  3434.     if (has_mbyte)
  3435.     {
  3436.         int i, mb_len;
  3437.  
  3438.         mb_len = (*mb_ptr2len_check)(src) - 1;
  3439.         if (mb_len > 0 && len >= mb_len)
  3440.         for (i = 0; i < mb_len; ++i)
  3441.         {
  3442.             --len;
  3443.             ++src;
  3444.             if (dest != NULL)
  3445.             *dest++ = *src;
  3446.         }
  3447.     }
  3448. #endif
  3449.     }
  3450.     if (dest != NULL)
  3451.     *dest = NUL;
  3452.  
  3453.     return m;
  3454. }
  3455. #endif /* FEAT_INS_EXPAND */
  3456.  
  3457. /*
  3458.  * Next character is interpreted literally.
  3459.  * A one, two or three digit decimal number is interpreted as its byte value.
  3460.  * If one or two digits are entered, the next character is given to vungetc().
  3461.  * For Unicode a character > 255 may be returned.
  3462.  */
  3463.     int
  3464. get_literal()
  3465. {
  3466.     int        cc;
  3467.     int        nc;
  3468.     int        i;
  3469.     int        hex = FALSE;
  3470.     int        octal = FALSE;
  3471. #ifdef FEAT_MBYTE
  3472.     int        unicode = 0;
  3473. #endif
  3474.  
  3475.     if (got_int)
  3476.     return Ctrl_C;
  3477.  
  3478. #ifdef FEAT_GUI
  3479.     /*
  3480.      * In GUI there is no point inserting the internal code for a special key.
  3481.      * It is more useful to insert the string "<KEY>" instead.    This would
  3482.      * probably be useful in a text window too, but it would not be
  3483.      * vi-compatible (maybe there should be an option for it?) -- webb
  3484.      */
  3485.     if (gui.in_use)
  3486.     ++allow_keys;
  3487. #endif
  3488. #ifdef USE_ON_FLY_SCROLL
  3489.     dont_scroll = TRUE;        /* disallow scrolling here */
  3490. #endif
  3491.     ++no_mapping;        /* don't map the next key hits */
  3492.     cc = 0;
  3493.     i = 0;
  3494.     for (;;)
  3495.     {
  3496.     do
  3497.         nc = safe_vgetc();
  3498.     while (nc == K_IGNORE || nc == K_VER_SCROLLBAR
  3499.                             || nc == K_HOR_SCROLLBAR);
  3500. #ifdef FEAT_CMDL_INFO
  3501.     if (!(State & CMDLINE)
  3502. # ifdef FEAT_MBYTE
  3503.         && MB_BYTE2LEN_CHECK(nc) == 1
  3504. # endif
  3505.        )
  3506.         add_to_showcmd(nc);
  3507. #endif
  3508.     if (nc == 'x' || nc == 'X')
  3509.         hex = TRUE;
  3510.     else if (nc == 'o' || nc == 'O')
  3511.         octal = TRUE;
  3512. #ifdef FEAT_MBYTE
  3513.     else if (nc == 'u' || nc == 'U')
  3514.         unicode = nc;
  3515. #endif
  3516.     else
  3517.     {
  3518.         if (hex
  3519. #ifdef FEAT_MBYTE
  3520.             || unicode != 0
  3521. #endif
  3522.             )
  3523.         {
  3524.         /* Careful: isxdigit() on Win32 can handle only 0-255 */
  3525.         if (nc < 0 || nc > 255 || (!vim_isdigit(nc) && !isxdigit(nc)))
  3526.             break;
  3527.         cc = cc * 16 + hex2nr(nc);
  3528.         }
  3529.         else if (octal)
  3530.         {
  3531.         if (!vim_isdigit(nc) || (nc > '7'))
  3532.             break;
  3533.         cc = cc * 8 + nc - '0';
  3534.         }
  3535.         else
  3536.         {
  3537.         if (!vim_isdigit(nc))
  3538.             break;
  3539.         cc = cc * 10 + nc - '0';
  3540.         }
  3541.  
  3542.         ++i;
  3543.     }
  3544.  
  3545.     if (cc > 255
  3546. #ifdef FEAT_MBYTE
  3547.         && unicode == 0
  3548. #endif
  3549.         )
  3550.         cc = 255;        /* limit range to 0-255 */
  3551.     nc = 0;
  3552.  
  3553.     if (hex)        /* hex: up to two chars */
  3554.     {
  3555.         if (i >= 2)
  3556.         break;
  3557.     }
  3558. #ifdef FEAT_MBYTE
  3559.     else if (unicode)    /* Unicode: up to four or eight chars */
  3560.     {
  3561.         if ((unicode == 'u' && i >= 4) || (unicode == 'U' && i >= 8))
  3562.         break;
  3563.     }
  3564. #endif
  3565.     else if (i >= 3)    /* decimal or octal: up to three chars */
  3566.         break;
  3567.     }
  3568.     if (i == 0)        /* no number entered */
  3569.     {
  3570.     if (nc == K_ZERO)   /* NUL is stored as NL */
  3571.     {
  3572.         cc = '\n';
  3573.         nc = 0;
  3574.     }
  3575.     else
  3576.     {
  3577.         cc = nc;
  3578.         nc = 0;
  3579.     }
  3580.     }
  3581.  
  3582.     if (cc == 0)    /* NUL is stored as NL */
  3583.     cc = '\n';
  3584.  
  3585.     --no_mapping;
  3586. #ifdef FEAT_GUI
  3587.     if (gui.in_use)
  3588.     --allow_keys;
  3589. #endif
  3590.     if (nc)
  3591.     vungetc(nc);
  3592.     got_int = FALSE;        /* CTRL-C typed after CTRL-V is not an interrupt */
  3593.     return cc;
  3594. }
  3595.  
  3596. /*
  3597.  * Insert character, taking care of special keys and mod_mask
  3598.  */
  3599.     static void
  3600. insert_special(c, allow_modmask, ctrlv)
  3601.     int        c;
  3602.     int        allow_modmask;
  3603.     int        ctrlv;        /* c was typed after CTRL-V */
  3604. {
  3605.     char_u  *p;
  3606.     int        len;
  3607.  
  3608.     /*
  3609.      * Special function key, translate into "<Key>". Up to the last '>' is
  3610.      * inserted with ins_str(), so as not to replace characters in replace
  3611.      * mode.
  3612.      * Only use mod_mask for special keys, to avoid things like <S-Space>,
  3613.      * unless 'allow_modmask' is TRUE.
  3614.      */
  3615.     if (IS_SPECIAL(c) || (mod_mask && allow_modmask))
  3616.     {
  3617.     p = get_special_key_name(c, mod_mask);
  3618.     len = (int)STRLEN(p);
  3619.     c = p[len - 1];
  3620.     if (len > 2)
  3621.     {
  3622.         if (stop_arrow() == FAIL)
  3623.         return;
  3624.         p[len - 1] = NUL;
  3625.         ins_str(p);
  3626.         AppendToRedobuffLit(p);
  3627.         ctrlv = FALSE;
  3628.     }
  3629.     }
  3630.     if (stop_arrow() == OK)
  3631.     insertchar(c, ctrlv ? INSCHAR_CTRLV : 0, -1);
  3632. }
  3633.  
  3634. /*
  3635.  * Special characters in this context are those that need processing other
  3636.  * than the simple insertion that can be performed here. This includes ESC
  3637.  * which terminates the insert, and CR/NL which need special processing to
  3638.  * open up a new line. This routine tries to optimize insertions performed by
  3639.  * the "redo", "undo" or "put" commands, so it needs to know when it should
  3640.  * stop and defer processing to the "normal" mechanism.
  3641.  * '0' and '^' are special, because they can be followed by CTRL-D.
  3642.  */
  3643. #ifdef EBCDIC
  3644. # define ISSPECIAL(c)    ((c) < ' ' || (c) == '0' || (c) == '^')
  3645. #else
  3646. # define ISSPECIAL(c)    ((c) < ' ' || (c) >= DEL || (c) == '0' || (c) == '^')
  3647. #endif
  3648.  
  3649.     void
  3650. insertchar(c, flags, second_indent)
  3651.     int        c;            /* character to insert or NUL */
  3652.     int        flags;            /* INSCHAR_FORMAT, etc. */
  3653.     int        second_indent;        /* indent for second line if >= 0 */
  3654. {
  3655.     int        haveto_redraw = FALSE;
  3656.     int        textwidth;
  3657. #ifdef FEAT_COMMENTS
  3658.     colnr_T    leader_len;
  3659.     char_u    *p;
  3660.     int        no_leader = FALSE;
  3661.     int        do_comments = (flags & INSCHAR_DO_COM);
  3662. #endif
  3663.     int        first_line = TRUE;
  3664.     int        fo_ins_blank;
  3665. #ifdef FEAT_MBYTE
  3666.     int        fo_multibyte;
  3667. #endif
  3668.     int        save_char = NUL;
  3669.     int        cc;
  3670.  
  3671.     textwidth = comp_textwidth(flags & INSCHAR_FORMAT);
  3672.     fo_ins_blank = has_format_option(FO_INS_BLANK);
  3673. #ifdef FEAT_MBYTE
  3674.     fo_multibyte = has_format_option(FO_MULTIBYTE);
  3675. #endif
  3676.  
  3677.     /*
  3678.      * Try to break the line in two or more pieces when:
  3679.      * - Always do this if we have been called to do formatting only.
  3680.      * - Otherwise:
  3681.      *     - Don't do this if inserting a blank
  3682.      *     - Don't do this if an existing character is being replaced, unless
  3683.      *       we're in VREPLACE mode.
  3684.      *     - Do this if the cursor is not on the line where insert started
  3685.      *     or - 'formatoptions' doesn't have 'l' or the line was not too long
  3686.      *           before the insert.
  3687.      *        - 'formatoptions' doesn't have 'b' or a blank was inserted at or
  3688.      *          before 'textwidth'
  3689.      */
  3690.     if (textwidth
  3691.         && ((flags & INSCHAR_FORMAT)
  3692.         || (!vim_iswhite(c)
  3693.             && !((State & REPLACE_FLAG)
  3694. #ifdef FEAT_VREPLACE
  3695.             && !(State & VREPLACE_FLAG)
  3696. #endif
  3697.             && *ml_get_cursor() != NUL)
  3698.             && (curwin->w_cursor.lnum != Insstart.lnum
  3699.             || ((!has_format_option(FO_INS_LONG)
  3700.                 || Insstart_textlen <= (colnr_T)textwidth)
  3701.                 && (!fo_ins_blank
  3702.                 || Insstart_blank_vcol <= (colnr_T)textwidth
  3703.                 ))))))
  3704.     {
  3705.     /*
  3706.      * When 'ai' is off we don't want a space under the cursor to be
  3707.      * deleted.  Replace it with an 'x' temporarily.
  3708.      */
  3709.     if (!curbuf->b_p_ai)
  3710.     {
  3711.         cc = gchar_cursor();
  3712.         if (vim_iswhite(cc))
  3713.         {
  3714.         save_char = cc;
  3715.         pchar_cursor('x');
  3716.         }
  3717.     }
  3718.  
  3719.     /*
  3720.      * Repeat breaking lines, until the current line is not too long.
  3721.      */
  3722.     while (!got_int)
  3723.     {
  3724.         int        startcol;        /* Cursor column at entry */
  3725.         int        wantcol;        /* column at textwidth border */
  3726.         int        foundcol;        /* column for start of spaces */
  3727.         int        end_foundcol = 0;    /* column for start of word */
  3728.         colnr_T    len;
  3729.         colnr_T    virtcol;
  3730. #ifdef FEAT_VREPLACE
  3731.         int        orig_col = 0;
  3732.         char_u    *saved_text = NULL;
  3733. #endif
  3734.         colnr_T    col;
  3735.  
  3736.         virtcol = get_nolist_virtcol();
  3737.         if (virtcol < (colnr_T)textwidth)
  3738.         break;
  3739.  
  3740. #ifdef FEAT_COMMENTS
  3741.         if (no_leader)
  3742.         do_comments = FALSE;
  3743.         else if (!(flags & INSCHAR_FORMAT)
  3744.                        && has_format_option(FO_WRAP_COMS))
  3745.         do_comments = TRUE;
  3746.  
  3747.         /* Don't break until after the comment leader */
  3748.         if (do_comments)
  3749.         leader_len = get_leader_len(ml_get_curline(), NULL, FALSE);
  3750.         else
  3751.         leader_len = 0;
  3752.  
  3753.         /* If the line doesn't start with a comment leader, then don't
  3754.          * start one in a following broken line.  Avoids that a %word
  3755.          * moved to the start of the next line causes all following lines
  3756.          * to start with %. */
  3757.         if (leader_len == 0)
  3758.         no_leader = TRUE;
  3759. #endif
  3760.         if (!(flags & INSCHAR_FORMAT)
  3761. #ifdef FEAT_COMMENTS
  3762.             && leader_len == 0
  3763. #endif
  3764.             && !has_format_option(FO_WRAP))
  3765.  
  3766.         {
  3767.         textwidth = 0;
  3768.         break;
  3769.         }
  3770.         if ((startcol = curwin->w_cursor.col) == 0)
  3771.         break;
  3772.  
  3773.         /* find column of textwidth border */
  3774.         coladvance((colnr_T)textwidth);
  3775.         wantcol = curwin->w_cursor.col;
  3776.  
  3777.         curwin->w_cursor.col = startcol - 1;
  3778. #ifdef FEAT_MBYTE
  3779.         /* Correct cursor for multi-byte character. */
  3780.         if (has_mbyte)
  3781.         mb_adjust_cursor();
  3782. #endif
  3783.         foundcol = 0;
  3784.  
  3785.         /*
  3786.          * Find position to break at.
  3787.          * Stop at start of line.
  3788.          * Stop at first entered white when 'formatoptions' has 'v'
  3789.          */
  3790.         while (curwin->w_cursor.col > 0
  3791.             && ((!fo_ins_blank && !has_format_option(FO_INS_VI))
  3792.             || curwin->w_cursor.lnum != Insstart.lnum
  3793.             || curwin->w_cursor.col >= Insstart.col))
  3794.         {
  3795.         cc = gchar_cursor();
  3796. #ifdef FEAT_MBYTE
  3797.         if (cc >= 0x100 && fo_multibyte)
  3798.         {
  3799.             /* Break at a multi-byte character. */
  3800.             end_foundcol = curwin->w_cursor.col;
  3801.             foundcol = curwin->w_cursor.col;
  3802.             dec_cursor();
  3803.             if (curwin->w_cursor.col < (colnr_T)wantcol)
  3804.             break;
  3805.             continue;
  3806.         }
  3807. #endif
  3808.         if (vim_iswhite(cc))
  3809.         {
  3810.             /* remember position of blank just before text */
  3811.             end_foundcol = curwin->w_cursor.col;
  3812.  
  3813.             /* find start of sequence of blanks */
  3814.             while (curwin->w_cursor.col > 0 && vim_iswhite(cc))
  3815.             {
  3816.             dec_cursor();
  3817.             cc = gchar_cursor();
  3818.             }
  3819.             if (curwin->w_cursor.col == 0 && vim_iswhite(cc))
  3820.             break;        /* only spaces in front of text */
  3821. #ifdef FEAT_COMMENTS
  3822.             /* Don't break until after the comment leader */
  3823.             if (curwin->w_cursor.col < leader_len)
  3824.             break;
  3825. #endif
  3826.             if (has_format_option(FO_ONE_LETTER))
  3827.             {
  3828.             /* do not break after one-letter words */
  3829.             if (curwin->w_cursor.col == 0)
  3830.                 break;    /* one-letter word at begin */
  3831.  
  3832.             col = curwin->w_cursor.col;
  3833.             dec_cursor();
  3834.             cc = gchar_cursor();
  3835.  
  3836.             if (vim_iswhite(cc))
  3837.                 continue;    /* one-letter, continue */
  3838.             curwin->w_cursor.col = col;
  3839.             }
  3840. #ifdef FEAT_MBYTE
  3841.             if (has_mbyte)
  3842.             foundcol = curwin->w_cursor.col
  3843.                        + (*mb_ptr2len_check)(ml_get_cursor());
  3844.             else
  3845. #endif
  3846.             foundcol = curwin->w_cursor.col + 1;
  3847.             if (curwin->w_cursor.col < (colnr_T)wantcol)
  3848.             break;
  3849.         }
  3850.         dec_cursor();
  3851.         }
  3852.  
  3853.         if (foundcol == 0)        /* no spaces, cannot break line */
  3854.         {
  3855.         curwin->w_cursor.col = startcol;
  3856.         break;
  3857.         }
  3858.  
  3859.         /* Going to break the line, remove any "$" now. */
  3860.         undisplay_dollar();
  3861.  
  3862.         /*
  3863.          * Offset between cursor position and line break is used by replace
  3864.          * stack functions.  VREPLACE does not use this, and backspaces
  3865.          * over the text instead.
  3866.          */
  3867. #ifdef FEAT_VREPLACE
  3868.         if (State & VREPLACE_FLAG)
  3869.         orig_col = startcol;    /* Will start backspacing from here */
  3870.         else
  3871. #endif
  3872.         replace_offset = startcol - end_foundcol - 1;
  3873.  
  3874.         /*
  3875.          * adjust startcol for spaces that will be deleted and
  3876.          * characters that will remain on top line
  3877.          */
  3878.         curwin->w_cursor.col = foundcol;
  3879.         while (cc = gchar_cursor(), vim_iswhite(cc))
  3880.         inc_cursor();
  3881.         startcol -= curwin->w_cursor.col;
  3882.         if (startcol < 0)
  3883.         startcol = 0;
  3884.  
  3885. #ifdef FEAT_VREPLACE
  3886.         if (State & VREPLACE_FLAG)
  3887.         {
  3888.         /*
  3889.          * In VREPLACE mode, we will backspace over the text to be
  3890.          * wrapped, so save a copy now to put on the next line.
  3891.          */
  3892.         saved_text = vim_strsave(ml_get_cursor());
  3893.         curwin->w_cursor.col = orig_col;
  3894.         if (saved_text == NULL)
  3895.             break;    /* Can't do it, out of memory */
  3896.         saved_text[startcol] = NUL;
  3897.  
  3898.         /* Backspace over characters that will move to the next line */
  3899.         backspace_until_column(foundcol);
  3900.         }
  3901.         else
  3902. #endif
  3903.         {
  3904.         /* put cursor after pos. to break line */
  3905.         curwin->w_cursor.col = foundcol;
  3906.         }
  3907.  
  3908.         /*
  3909.          * Split the line just before the margin.
  3910.          * Only insert/delete lines, but don't really redraw the window.
  3911.          */
  3912.         open_line(FORWARD, OPENLINE_DELSPACES
  3913. #ifdef FEAT_COMMENTS
  3914.             + (do_comments ? OPENLINE_DO_COM : 0)
  3915. #endif
  3916.             , old_indent);
  3917.         old_indent = 0;
  3918.  
  3919.         replace_offset = 0;
  3920.         if (first_line)
  3921.         {
  3922.         if (second_indent < 0 && has_format_option(FO_Q_NUMBER))
  3923.             second_indent = get_number_indent(curwin->w_cursor.lnum -1);
  3924.         if (second_indent >= 0)
  3925.         {
  3926. #ifdef FEAT_VREPLACE
  3927.             if (State & VREPLACE_FLAG)
  3928.             change_indent(INDENT_SET, second_indent, FALSE, NUL);
  3929.             else
  3930. #endif
  3931.             (void)set_indent(second_indent, SIN_CHANGED);
  3932.         }
  3933.         first_line = FALSE;
  3934.         }
  3935.  
  3936. #ifdef FEAT_VREPLACE
  3937.         if (State & VREPLACE_FLAG)
  3938.         {
  3939.         /*
  3940.          * In VREPLACE mode we have backspaced over the text to be
  3941.          * moved, now we re-insert it into the new line.
  3942.          */
  3943.         ins_bytes(saved_text);
  3944.         vim_free(saved_text);
  3945.         }
  3946.         else
  3947. #endif
  3948.         {
  3949.         /*
  3950.          * Check if cursor is not past the NUL off the line, cindent
  3951.          * may have added or removed indent.
  3952.          */
  3953.         curwin->w_cursor.col += startcol;
  3954.         len = (colnr_T)STRLEN(ml_get_curline());
  3955.         if (curwin->w_cursor.col > len)
  3956.             curwin->w_cursor.col = len;
  3957.         }
  3958.  
  3959.         haveto_redraw = TRUE;
  3960. #ifdef FEAT_CINDENT
  3961.         can_cindent = TRUE;
  3962. #endif
  3963.         /* moved the cursor, don't autoindent or cindent now */
  3964.         did_ai = FALSE;
  3965. #ifdef FEAT_SMARTINDENT
  3966.         did_si = FALSE;
  3967.         can_si = FALSE;
  3968.         can_si_back = FALSE;
  3969. #endif
  3970.         line_breakcheck();
  3971.     }
  3972.  
  3973.     if (save_char)            /* put back space after cursor */
  3974.         pchar_cursor(save_char);
  3975.  
  3976.     if (c == NUL)            /* formatting only */
  3977.         return;
  3978.     if (haveto_redraw)
  3979.     {
  3980.         update_topline();
  3981.         redraw_curbuf_later(VALID);
  3982.     }
  3983.     }
  3984.     if (c == NUL)        /* only formatting was wanted */
  3985.     return;
  3986.  
  3987. #ifdef FEAT_COMMENTS
  3988.     /* Check whether this character should end a comment. */
  3989.     if (did_ai && (int)c == end_comment_pending)
  3990.     {
  3991.     char_u  *line;
  3992.     char_u    lead_end[COM_MAX_LEN];        /* end-comment string */
  3993.     int    middle_len, end_len;
  3994.     int    i;
  3995.  
  3996.     /*
  3997.      * Need to remove existing (middle) comment leader and insert end
  3998.      * comment leader.  First, check what comment leader we can find.
  3999.      */
  4000.     i = get_leader_len(line = ml_get_curline(), &p, FALSE);
  4001.     if (i > 0 && vim_strchr(p, COM_MIDDLE) != NULL)    /* Just checking */
  4002.     {
  4003.         /* Skip middle-comment string */
  4004.         while (*p && p[-1] != ':')    /* find end of middle flags */
  4005.         ++p;
  4006.         middle_len = copy_option_part(&p, lead_end, COM_MAX_LEN, ",");
  4007.         /* Don't count trailing white space for middle_len */
  4008.         while (middle_len > 0 && vim_iswhite(lead_end[middle_len - 1]))
  4009.         --middle_len;
  4010.  
  4011.         /* Find the end-comment string */
  4012.         while (*p && p[-1] != ':')    /* find end of end flags */
  4013.         ++p;
  4014.         end_len = copy_option_part(&p, lead_end, COM_MAX_LEN, ",");
  4015.  
  4016.         /* Skip white space before the cursor */
  4017.         i = curwin->w_cursor.col;
  4018.         while (--i >= 0 && vim_iswhite(line[i]))
  4019.         ;
  4020.         i++;
  4021.  
  4022.         /* Skip to before the middle leader */
  4023.         i -= middle_len;
  4024.  
  4025.         /* Check some expected things before we go on */
  4026.         if (i >= 0 && lead_end[end_len - 1] == end_comment_pending)
  4027.         {
  4028.         /* Backspace over all the stuff we want to replace */
  4029.         backspace_until_column(i);
  4030.  
  4031.         /*
  4032.          * Insert the end-comment string, except for the last
  4033.          * character, which will get inserted as normal later.
  4034.          */
  4035.         ins_bytes_len(lead_end, end_len - 1);
  4036.         }
  4037.     }
  4038.     }
  4039.     end_comment_pending = NUL;
  4040. #endif
  4041.  
  4042.     did_ai = FALSE;
  4043. #ifdef FEAT_SMARTINDENT
  4044.     did_si = FALSE;
  4045.     can_si = FALSE;
  4046.     can_si_back = FALSE;
  4047. #endif
  4048.  
  4049.     /*
  4050.      * If there's any pending input, grab up to INPUT_BUFLEN at once.
  4051.      * This speeds up normal text input considerably.
  4052.      * Don't do this when 'cindent' or 'indentexpr' is set, because we might
  4053.      * need to re-indent at a ':', or any other character (but not what
  4054.      * 'paste' is set)..
  4055.      */
  4056. #ifdef USE_ON_FLY_SCROLL
  4057.     dont_scroll = FALSE;        /* allow scrolling here */
  4058. #endif
  4059.  
  4060.     if (       !ISSPECIAL(c)
  4061. #ifdef FEAT_MBYTE
  4062.         && (!has_mbyte || (*mb_char2len)(c) == 1)
  4063. #endif
  4064.         && vpeekc() != NUL
  4065.         && !(State & REPLACE_FLAG)
  4066. #ifdef FEAT_CINDENT
  4067.         && !cindent_on()
  4068. #endif
  4069. #ifdef FEAT_RIGHTLEFT
  4070.         && !p_ri
  4071. #endif
  4072.            )
  4073.     {
  4074. #define INPUT_BUFLEN 100
  4075.     char_u        buf[INPUT_BUFLEN + 1];
  4076.     int        i;
  4077.     colnr_T        virtcol = 0;
  4078.  
  4079.     buf[0] = c;
  4080.     i = 1;
  4081.     if (textwidth)
  4082.         virtcol = get_nolist_virtcol();
  4083.     /*
  4084.      * Stop the string when:
  4085.      * - no more chars available
  4086.      * - finding a special character (command key)
  4087.      * - buffer is full
  4088.      * - running into the 'textwidth' boundary
  4089.      * - need to check for abbreviation: A non-word char after a word-char
  4090.      */
  4091.     while (       (c = vpeekc()) != NUL
  4092.         && !ISSPECIAL(c)
  4093. #ifdef FEAT_MBYTE
  4094.         && (!has_mbyte || MB_BYTE2LEN_CHECK(c) == 1)
  4095. #endif
  4096.         && i < INPUT_BUFLEN
  4097.         && (textwidth == 0
  4098.             || (virtcol += byte2cells(buf[i - 1])) < (colnr_T)textwidth)
  4099.         && !(!no_abbr && !vim_iswordc(c) && vim_iswordc(buf[i - 1])))
  4100.     {
  4101. #ifdef FEAT_RIGHTLEFT
  4102.         c = vgetc();
  4103.         if (p_hkmap && KeyTyped)
  4104.         c = hkmap(c);            /* Hebrew mode mapping */
  4105. # ifdef FEAT_FKMAP
  4106.         if (p_fkmap && KeyTyped)
  4107.         c = fkmap(c);            /* Farsi mode mapping */
  4108. # endif
  4109.         buf[i++] = c;
  4110. #else
  4111.         buf[i++] = vgetc();
  4112. #endif
  4113.     }
  4114.  
  4115. #ifdef FEAT_DIGRAPHS
  4116.     do_digraph(-1);            /* clear digraphs */
  4117.     do_digraph(buf[i-1]);        /* may be the start of a digraph */
  4118. #endif
  4119.     buf[i] = NUL;
  4120.     ins_str(buf);
  4121.     if (flags & INSCHAR_CTRLV)
  4122.     {
  4123.         redo_literal(*buf);
  4124.         i = 1;
  4125.     }
  4126.     else
  4127.         i = 0;
  4128.     if (buf[i] != NUL)
  4129.         AppendToRedobuffLit(buf + i);
  4130.     }
  4131.     else
  4132.     {
  4133. #ifdef FEAT_MBYTE
  4134.     if (has_mbyte && (cc = (*mb_char2len)(c)) > 1)
  4135.     {
  4136.         char_u    buf[MB_MAXBYTES + 1];
  4137.  
  4138.         (*mb_char2bytes)(c, buf);
  4139.         buf[cc] = NUL;
  4140.         ins_char_bytes(buf, cc);
  4141.         AppendCharToRedobuff(c);
  4142.     }
  4143.     else
  4144. #endif
  4145.     {
  4146.         ins_char(c);
  4147.         if (flags & INSCHAR_CTRLV)
  4148.         redo_literal(c);
  4149.         else
  4150.         AppendCharToRedobuff(c);
  4151.     }
  4152.     }
  4153. }
  4154.  
  4155. /*
  4156.  * Find out textwidth to be used for formatting:
  4157.  *    if 'textwidth' option is set, use it
  4158.  *    else if 'wrapmargin' option is set, use W_WIDTH(curwin) - 'wrapmargin'
  4159.  *    if invalid value, use 0.
  4160.  *    Set default to window width (maximum 79) for "Q" command.
  4161.  */
  4162.     int
  4163. comp_textwidth(ff)
  4164.     int        ff;    /* force formatting (for "Q" command) */
  4165. {
  4166.     int        textwidth;
  4167.  
  4168.     textwidth = curbuf->b_p_tw;
  4169.     if (textwidth == 0 && curbuf->b_p_wm)
  4170.     textwidth = W_WIDTH(curwin) - curbuf->b_p_wm;
  4171.     if (textwidth < 0)
  4172.     textwidth = 0;
  4173.     if (ff && textwidth == 0)
  4174.     {
  4175.     textwidth = W_WIDTH(curwin) - 1;
  4176.     if (textwidth > 79)
  4177.         textwidth = 79;
  4178.     }
  4179.     return textwidth;
  4180. }
  4181.  
  4182. /*
  4183.  * Put a character in the redo buffer, for when just after a CTRL-V.
  4184.  */
  4185.     static void
  4186. redo_literal(c)
  4187.     int        c;
  4188. {
  4189.     char_u    buf[10];
  4190.  
  4191.     /* Only digits need special treatment.  Translate them into a string of
  4192.      * three digits. */
  4193.     if (vim_isdigit(c))
  4194.     {
  4195.     sprintf((char *)buf, "%03d", c);
  4196.     AppendToRedobuff(buf);
  4197.     }
  4198.     else
  4199.     AppendCharToRedobuff(c);
  4200. }
  4201.  
  4202. /*
  4203.  * start_arrow() is called when an arrow key is used in insert mode.
  4204.  * It resembles hitting the <ESC> key.
  4205.  */
  4206.     static void
  4207. start_arrow(end_insert_pos)
  4208.     pos_T    *end_insert_pos;
  4209. {
  4210.     if (!arrow_used)        /* something has been inserted */
  4211.     {
  4212.     AppendToRedobuff(ESC_STR);
  4213.     arrow_used = TRUE;    /* this means we stopped the current insert */
  4214.     stop_insert(end_insert_pos);
  4215.     }
  4216. }
  4217.  
  4218. /*
  4219.  * stop_arrow() is called before a change is made in insert mode.
  4220.  * If an arrow key has been used, start a new insertion.
  4221.  * Returns FAIL if undo is impossible, shouldn't insert then.
  4222.  */
  4223.     int
  4224. stop_arrow()
  4225. {
  4226.     if (arrow_used)
  4227.     {
  4228.     if (u_save_cursor() == OK)
  4229.     {
  4230.         arrow_used = FALSE;
  4231.         ins_need_undo = FALSE;
  4232.     }
  4233.     Insstart = curwin->w_cursor;    /* new insertion starts here */
  4234.     Insstart_textlen = linetabsize(ml_get_curline());
  4235.     ai_col = 0;
  4236. #ifdef FEAT_VREPLACE
  4237.     if (State & VREPLACE_FLAG)
  4238.     {
  4239.         orig_line_count = curbuf->b_ml.ml_line_count;
  4240.         vr_lines_changed = 1;
  4241.     }
  4242. #endif
  4243.     ResetRedobuff();
  4244.     AppendToRedobuff((char_u *)"1i");   /* pretend we start an insertion */
  4245.     }
  4246.     else if (ins_need_undo)
  4247.     {
  4248.     if (u_save_cursor() == OK)
  4249.         ins_need_undo = FALSE;
  4250.     }
  4251.  
  4252. #ifdef FEAT_FOLDING
  4253.     /* Always open fold at the cursor line when inserting something. */
  4254.     foldOpenCursor();
  4255. #endif
  4256.  
  4257.     return (arrow_used || ins_need_undo ? FAIL : OK);
  4258. }
  4259.  
  4260. /*
  4261.  * do a few things to stop inserting
  4262.  */
  4263.     static void
  4264. stop_insert(end_insert_pos)
  4265.     pos_T    *end_insert_pos;    /* where insert ended */
  4266. {
  4267.     int        cc;
  4268.  
  4269.     stop_redo_ins();
  4270.     replace_flush();        /* abandon replace stack */
  4271.  
  4272.     /*
  4273.      * save the inserted text for later redo with ^@
  4274.      */
  4275.     vim_free(last_insert);
  4276.     last_insert = get_inserted();
  4277.     last_insert_skip = new_insert_skip;
  4278.  
  4279.     /*
  4280.      * If we just did an auto-indent, remove the white space from the end of
  4281.      * the line, and put the cursor back.
  4282.      */
  4283.     if (did_ai && !arrow_used)
  4284.     {
  4285.     if (gchar_cursor() == NUL && curwin->w_cursor.col > 0)
  4286.         --curwin->w_cursor.col;
  4287.     while (cc = gchar_cursor(), vim_iswhite(cc))
  4288.         (void)del_char(TRUE);
  4289.     if (cc != NUL)
  4290.         ++curwin->w_cursor.col;    /* put cursor back on the NUL */
  4291.     }
  4292.     did_ai = FALSE;
  4293. #ifdef FEAT_SMARTINDENT
  4294.     did_si = FALSE;
  4295.     can_si = FALSE;
  4296.     can_si_back = FALSE;
  4297. #endif
  4298.  
  4299.     /* set '[ and '] to the inserted text */
  4300.     curbuf->b_op_start = Insstart;
  4301.     curbuf->b_op_end = *end_insert_pos;
  4302. }
  4303.  
  4304. /*
  4305.  * Set the last inserted text to a single character.
  4306.  * Used for the replace command.
  4307.  */
  4308.     void
  4309. set_last_insert(c)
  4310.     int        c;
  4311. {
  4312.     char_u    *s;
  4313.  
  4314.     vim_free(last_insert);
  4315. #ifdef FEAT_MBYTE
  4316.     last_insert = alloc(MB_MAXBYTES * 3 + 5);
  4317. #else
  4318.     last_insert = alloc(6);
  4319. #endif
  4320.     if (last_insert != NULL)
  4321.     {
  4322.     s = last_insert;
  4323.     /* Use the CTRL-V only when entering a special char */
  4324.     if (c < ' ' || c == DEL)
  4325.         *s++ = Ctrl_V;
  4326.     s = add_char2buf(c, s);
  4327.     *s++ = ESC;
  4328.     *s++ = NUL;
  4329.     last_insert_skip = 0;
  4330.     }
  4331. }
  4332.  
  4333. /*
  4334.  * Add character "c" to buffer "s".  Escape the special meaning of K_SPECIAL
  4335.  * and CSI.  Handle multi-byte characters.
  4336.  * Returns a pointer to after the added bytes.
  4337.  */
  4338.     char_u *
  4339. add_char2buf(c, s)
  4340.     int        c;
  4341.     char_u    *s;
  4342. {
  4343. #ifdef FEAT_MBYTE
  4344.     char_u    temp[MB_MAXBYTES];
  4345.     int        i;
  4346.     int        len;
  4347.  
  4348.     len = (*mb_char2bytes)(c, temp);
  4349.     for (i = 0; i < len; ++i)
  4350.     {
  4351.     c = temp[i];
  4352. #endif
  4353.     /* Need to escape K_SPECIAL and CSI like in the typeahead buffer. */
  4354.     if (c == K_SPECIAL)
  4355.     {
  4356.         *s++ = K_SPECIAL;
  4357.         *s++ = KS_SPECIAL;
  4358.         *s++ = KE_FILLER;
  4359.     }
  4360. #ifdef FEAT_GUI
  4361.     else if (c == CSI)
  4362.     {
  4363.         *s++ = CSI;
  4364.         *s++ = KS_EXTRA;
  4365.         *s++ = (int)KE_CSI;
  4366.     }
  4367. #endif
  4368.     else
  4369.         *s++ = c;
  4370. #ifdef FEAT_MBYTE
  4371.     }
  4372. #endif
  4373.     return s;
  4374. }
  4375.  
  4376. /*
  4377.  * move cursor to start of line
  4378.  * if flags & BL_WHITE    move to first non-white
  4379.  * if flags & BL_SOL    move to first non-white if startofline is set,
  4380.  *                otherwise keep "curswant" column
  4381.  * if flags & BL_FIX    don't leave the cursor on a NUL.
  4382.  */
  4383.     void
  4384. beginline(flags)
  4385.     int        flags;
  4386. {
  4387.     if ((flags & BL_SOL) && !p_sol)
  4388.     coladvance(curwin->w_curswant);
  4389.     else
  4390.     {
  4391.     curwin->w_cursor.col = 0;
  4392. #ifdef FEAT_VIRTUALEDIT
  4393.     curwin->w_cursor.coladd = 0;
  4394. #endif
  4395.  
  4396.     if (flags & (BL_WHITE | BL_SOL))
  4397.     {
  4398.         char_u  *ptr;
  4399.  
  4400.         for (ptr = ml_get_curline(); vim_iswhite(*ptr)
  4401.                    && !((flags & BL_FIX) && ptr[1] == NUL); ++ptr)
  4402.         ++curwin->w_cursor.col;
  4403.     }
  4404.     curwin->w_set_curswant = TRUE;
  4405.     }
  4406. }
  4407.  
  4408. /*
  4409.  * oneright oneleft cursor_down cursor_up
  4410.  *
  4411.  * Move one char {right,left,down,up}.
  4412.  * Doesn't move onto the NUL past the end of the line.
  4413.  * Return OK when successful, FAIL when we hit a line of file boundary.
  4414.  */
  4415.  
  4416.     int
  4417. oneright()
  4418. {
  4419.     char_u    *ptr;
  4420. #ifdef FEAT_MBYTE
  4421.     int        l;
  4422. #endif
  4423.  
  4424. #ifdef FEAT_VIRTUALEDIT
  4425.     if (virtual_active())
  4426.     {
  4427.     /* Adjust for multi-wide char (not include TAB) */
  4428.     ptr = ml_get_cursor();
  4429.     coladvance(getviscol() + ((*ptr != TAB && *ptr != NUL)
  4430.             ? ptr2cells(ptr) : 1));
  4431.     curwin->w_set_curswant = TRUE;
  4432.     return OK;
  4433.     }
  4434. #endif
  4435.  
  4436.     ptr = ml_get_cursor();
  4437. #ifdef FEAT_MBYTE
  4438.     if (has_mbyte && (l = (*mb_ptr2len_check)(ptr)) > 1)
  4439.     {
  4440.     /* The character under the cursor is a multi-byte character, move
  4441.      * several bytes right, but don't end up on the NUL. */
  4442.     if (ptr[l] == NUL)
  4443.         return FAIL;
  4444.     curwin->w_cursor.col += l;
  4445.     }
  4446.     else
  4447. #endif
  4448.     {
  4449.     if (*ptr++ == NUL || *ptr == NUL)
  4450.         return FAIL;
  4451.     ++curwin->w_cursor.col;
  4452.     }
  4453.  
  4454.     curwin->w_set_curswant = TRUE;
  4455.     return OK;
  4456. }
  4457.  
  4458.     int
  4459. oneleft()
  4460. {
  4461. #ifdef FEAT_VIRTUALEDIT
  4462.     if (virtual_active())
  4463.     {
  4464.     int width;
  4465.     char_u *ptr;
  4466.     int v = getviscol();
  4467.  
  4468.     if (v == 0)
  4469.         return FAIL;
  4470.  
  4471.     coladvance(v - 1);
  4472.     /* Adjust for multi-wide char (not include TAB) */
  4473.     ptr = ml_get_cursor();
  4474.     if (*ptr != TAB && *ptr != NUL && (width = ptr2cells(ptr)) > 1)
  4475.         coladvance(v - width);
  4476.  
  4477.     curwin->w_set_curswant = TRUE;
  4478.     return OK;
  4479.     }
  4480. #endif
  4481.  
  4482.     if (curwin->w_cursor.col == 0)
  4483.     return FAIL;
  4484.  
  4485.     curwin->w_set_curswant = TRUE;
  4486.     --curwin->w_cursor.col;
  4487.  
  4488. #ifdef FEAT_MBYTE
  4489.     /* if the character on the left of the current cursor is a multi-byte
  4490.      * character, move to its first byte */
  4491.     if (has_mbyte)
  4492.     mb_adjust_cursor();
  4493. #endif
  4494.     return OK;
  4495. }
  4496.  
  4497.     int
  4498. cursor_up(n, upd_topline)
  4499.     long    n;
  4500.     int        upd_topline;        /* When TRUE: update topline */
  4501. {
  4502.     linenr_T    lnum;
  4503.  
  4504.     if (n > 0)
  4505.     {
  4506.     lnum = curwin->w_cursor.lnum;
  4507.     if (lnum <= 1)
  4508.         return FAIL;
  4509.     if (n >= lnum)
  4510.         lnum = 1;
  4511.     else
  4512. #ifdef FEAT_FOLDING
  4513.         if (hasAnyFolding(curwin))
  4514.     {
  4515.         /*
  4516.          * Count each sequence of folded lines as one logical line.
  4517.          */
  4518.         /* go to the the start of the current fold */
  4519.         (void)hasFolding(lnum, &lnum, NULL);
  4520.  
  4521.         while (n--)
  4522.         {
  4523.         /* move up one line */
  4524.         --lnum;
  4525.         if (lnum <= 1)
  4526.             break;
  4527.         /* If we entered a fold, move to the beginning, unless in
  4528.          * Insert mode or when 'foldopen' contains "all": it will open
  4529.          * in a moment. */
  4530.         if (n > 0 || !((State & INSERT) || (fdo_flags & FDO_ALL)))
  4531.             (void)hasFolding(lnum, &lnum, NULL);
  4532.         }
  4533.         if (lnum < 1)
  4534.         lnum = 1;
  4535.     }
  4536.     else
  4537. #endif
  4538.         lnum -= n;
  4539.     curwin->w_cursor.lnum = lnum;
  4540.     }
  4541.  
  4542.     /* try to advance to the column we want to be at */
  4543.     coladvance(curwin->w_curswant);
  4544.  
  4545.     if (upd_topline)
  4546.     update_topline();    /* make sure curwin->w_topline is valid */
  4547.  
  4548.     return OK;
  4549. }
  4550.  
  4551. /*
  4552.  * Cursor down a number of logical lines.
  4553.  */
  4554.     int
  4555. cursor_down(n, upd_topline)
  4556.     long    n;
  4557.     int        upd_topline;        /* When TRUE: update topline */
  4558. {
  4559.     linenr_T    lnum;
  4560.  
  4561.     if (n > 0)
  4562.     {
  4563.     lnum = curwin->w_cursor.lnum;
  4564. #ifdef FEAT_FOLDING
  4565.     /* Move to last line of fold, will fail if it's the end-of-file. */
  4566.     (void)hasFolding(lnum, NULL, &lnum);
  4567. #endif
  4568.     if (lnum >= curbuf->b_ml.ml_line_count)
  4569.         return FAIL;
  4570.     if (lnum + n >= curbuf->b_ml.ml_line_count)
  4571.         lnum = curbuf->b_ml.ml_line_count;
  4572.     else
  4573. #ifdef FEAT_FOLDING
  4574.     if (hasAnyFolding(curwin))
  4575.     {
  4576.         linenr_T    last;
  4577.  
  4578.         /* count each sequence of folded lines as one logical line */
  4579.         while (n--)
  4580.         {
  4581.         if (hasFolding(lnum, NULL, &last))
  4582.             lnum = last + 1;
  4583.         else
  4584.             ++lnum;
  4585.         if (lnum >= curbuf->b_ml.ml_line_count)
  4586.             break;
  4587.         }
  4588.         if (lnum > curbuf->b_ml.ml_line_count)
  4589.         lnum = curbuf->b_ml.ml_line_count;
  4590.     }
  4591.     else
  4592. #endif
  4593.         lnum += n;
  4594.     curwin->w_cursor.lnum = lnum;
  4595.     }
  4596.  
  4597.     /* try to advance to the column we want to be at */
  4598.     coladvance(curwin->w_curswant);
  4599.  
  4600.     if (upd_topline)
  4601.     update_topline();    /* make sure curwin->w_topline is valid */
  4602.  
  4603.     return OK;
  4604. }
  4605.  
  4606. /*
  4607.  * Stuff the last inserted text in the read buffer.
  4608.  * Last_insert actually is a copy of the redo buffer, so we
  4609.  * first have to remove the command.
  4610.  */
  4611.     int
  4612. stuff_inserted(c, count, no_esc)
  4613.     int        c;        /* Command character to be inserted */
  4614.     long    count;    /* Repeat this many times */
  4615.     int        no_esc;    /* Don't add an ESC at the end */
  4616. {
  4617.     char_u    *esc_ptr;
  4618.     char_u    *ptr;
  4619.     char_u    *last_ptr;
  4620.     char_u    last = NUL;
  4621.  
  4622.     ptr = get_last_insert();
  4623.     if (ptr == NULL)
  4624.     {
  4625.     EMSG(_(e_noinstext));
  4626.     return FAIL;
  4627.     }
  4628.  
  4629.     /* may want to stuff the command character, to start Insert mode */
  4630.     if (c != NUL)
  4631.     stuffcharReadbuff(c);
  4632.     if ((esc_ptr = (char_u *)vim_strrchr(ptr, ESC)) != NULL)
  4633.     *esc_ptr = NUL;        /* remove the ESC */
  4634.  
  4635.     /* when the last char is either "0" or "^" it will be quoted if no ESC
  4636.      * comes after it OR if it will inserted more than once and "ptr"
  4637.      * starts with ^D.    -- Acevedo
  4638.      */
  4639.     last_ptr = (esc_ptr ? esc_ptr : ptr + STRLEN(ptr)) - 1;
  4640.     if (last_ptr >= ptr && (*last_ptr == '0' || *last_ptr == '^')
  4641.         && (no_esc || (*ptr == Ctrl_D && count > 1)))
  4642.     {
  4643.     last = *last_ptr;
  4644.     *last_ptr = NUL;
  4645.     }
  4646.  
  4647.     do
  4648.     {
  4649.     stuffReadbuff(ptr);
  4650.     /* a trailing "0" is inserted as "<C-V>048", "^" as "<C-V>^" */
  4651.     if (last)
  4652.         stuffReadbuff((char_u *)(last == '0'
  4653.             ? IF_EB("\026\060\064\070", CTRL_V_STR "xf0")
  4654.             : IF_EB("\026^", CTRL_V_STR "^")));
  4655.     }
  4656.     while (--count > 0);
  4657.  
  4658.     if (last)
  4659.     *last_ptr = last;
  4660.  
  4661.     if (esc_ptr != NULL)
  4662.     *esc_ptr = ESC;        /* put the ESC back */
  4663.  
  4664.     /* may want to stuff a trailing ESC, to get out of Insert mode */
  4665.     if (!no_esc)
  4666.     stuffcharReadbuff(ESC);
  4667.  
  4668.     return OK;
  4669. }
  4670.  
  4671.     char_u *
  4672. get_last_insert()
  4673. {
  4674.     if (last_insert == NULL)
  4675.     return NULL;
  4676.     return last_insert + last_insert_skip;
  4677. }
  4678.  
  4679. /*
  4680.  * Get last inserted string, and remove trailing <Esc>.
  4681.  * Returns pointer to allocated memory (must be freed) or NULL.
  4682.  */
  4683.     char_u *
  4684. get_last_insert_save()
  4685. {
  4686.     char_u    *s;
  4687.     int        len;
  4688.  
  4689.     if (last_insert == NULL)
  4690.     return NULL;
  4691.     s = vim_strsave(last_insert + last_insert_skip);
  4692.     if (s != NULL)
  4693.     {
  4694.     len = (int)STRLEN(s);
  4695.     if (len > 0 && s[len - 1] == ESC)    /* remove trailing ESC */
  4696.         s[len - 1] = NUL;
  4697.     }
  4698.     return s;
  4699. }
  4700.  
  4701. /*
  4702.  * Check the word in front of the cursor for an abbreviation.
  4703.  * Called when the non-id character "c" has been entered.
  4704.  * When an abbreviation is recognized it is removed from the text and
  4705.  * the replacement string is inserted in typebuf.tb_buf[], followed by "c".
  4706.  */
  4707.     static int
  4708. echeck_abbr(c)
  4709.     int c;
  4710. {
  4711.     /* Don't check for abbreviation in paste mode, when disabled and just
  4712.      * after moving around with cursor keys. */
  4713.     if (p_paste || no_abbr || arrow_used)
  4714.     return FALSE;
  4715.  
  4716.     return check_abbr(c, ml_get_curline(), curwin->w_cursor.col,
  4717.         curwin->w_cursor.lnum == Insstart.lnum ? Insstart.col : 0);
  4718. }
  4719.  
  4720. /*
  4721.  * replace-stack functions
  4722.  *
  4723.  * When replacing characters, the replaced characters are remembered for each
  4724.  * new character.  This is used to re-insert the old text when backspacing.
  4725.  *
  4726.  * There is a NUL headed list of characters for each character that is
  4727.  * currently in the file after the insertion point.  When BS is used, one NUL
  4728.  * headed list is put back for the deleted character.
  4729.  *
  4730.  * For a newline, there are two NUL headed lists.  One contains the characters
  4731.  * that the NL replaced.  The extra one stores the characters after the cursor
  4732.  * that were deleted (always white space).
  4733.  *
  4734.  * Replace_offset is normally 0, in which case replace_push will add a new
  4735.  * character at the end of the stack.  If replace_offset is not 0, that many
  4736.  * characters will be left on the stack above the newly inserted character.
  4737.  */
  4738.  
  4739. char_u    *replace_stack = NULL;
  4740. long    replace_stack_nr = 0;        /* next entry in replace stack */
  4741. long    replace_stack_len = 0;        /* max. number of entries */
  4742.  
  4743.     void
  4744. replace_push(c)
  4745.     int        c;        /* character that is replaced (NUL is none) */
  4746. {
  4747.     char_u  *p;
  4748.  
  4749.     if (replace_stack_nr < replace_offset)    /* nothing to do */
  4750.     return;
  4751.     if (replace_stack_len <= replace_stack_nr)
  4752.     {
  4753.     replace_stack_len += 50;
  4754.     p = lalloc(sizeof(char_u) * replace_stack_len, TRUE);
  4755.     if (p == NULL)        /* out of memory */
  4756.     {
  4757.         replace_stack_len -= 50;
  4758.         return;
  4759.     }
  4760.     if (replace_stack != NULL)
  4761.     {
  4762.         mch_memmove(p, replace_stack,
  4763.                  (size_t)(replace_stack_nr * sizeof(char_u)));
  4764.         vim_free(replace_stack);
  4765.     }
  4766.     replace_stack = p;
  4767.     }
  4768.     p = replace_stack + replace_stack_nr - replace_offset;
  4769.     if (replace_offset)
  4770.     mch_memmove(p + 1, p, (size_t)(replace_offset * sizeof(char_u)));
  4771.     *p = c;
  4772.     ++replace_stack_nr;
  4773. }
  4774.  
  4775. /*
  4776.  * call replace_push(c) with replace_offset set to the first NUL.
  4777.  */
  4778.     static void
  4779. replace_push_off(c)
  4780.     int        c;
  4781. {
  4782.     char_u    *p;
  4783.  
  4784.     p = replace_stack + replace_stack_nr;
  4785.     for (replace_offset = 1; replace_offset < replace_stack_nr;
  4786.                                  ++replace_offset)
  4787.     if (*--p == NUL)
  4788.         break;
  4789.     replace_push(c);
  4790.     replace_offset = 0;
  4791. }
  4792.  
  4793. /*
  4794.  * Pop one item from the replace stack.
  4795.  * return -1 if stack empty
  4796.  * return replaced character or NUL otherwise
  4797.  */
  4798.     static int
  4799. replace_pop()
  4800. {
  4801.     if (replace_stack_nr == 0)
  4802.     return -1;
  4803.     return (int)replace_stack[--replace_stack_nr];
  4804. }
  4805.  
  4806. /*
  4807.  * Join the top two items on the replace stack.  This removes to "off"'th NUL
  4808.  * encountered.
  4809.  */
  4810.     static void
  4811. replace_join(off)
  4812.     int        off;    /* offset for which NUL to remove */
  4813. {
  4814.     int        i;
  4815.  
  4816.     for (i = replace_stack_nr; --i >= 0; )
  4817.     if (replace_stack[i] == NUL && off-- <= 0)
  4818.     {
  4819.         --replace_stack_nr;
  4820.         mch_memmove(replace_stack + i, replace_stack + i + 1,
  4821.                           (size_t)(replace_stack_nr - i));
  4822.         return;
  4823.     }
  4824. }
  4825.  
  4826. /*
  4827.  * Pop bytes from the replace stack until a NUL is found, and insert them
  4828.  * before the cursor.  Can only be used in REPLACE or VREPLACE mode.
  4829.  */
  4830.     static void
  4831. replace_pop_ins()
  4832. {
  4833.     int        cc;
  4834.     int        oldState = State;
  4835.  
  4836.     State = NORMAL;            /* don't want REPLACE here */
  4837.     while ((cc = replace_pop()) > 0)
  4838.     {
  4839. #ifdef FEAT_MBYTE
  4840.     mb_replace_pop_ins(cc);
  4841. #else
  4842.     ins_char(cc);
  4843. #endif
  4844.     dec_cursor();
  4845.     }
  4846.     State = oldState;
  4847. }
  4848.  
  4849. #ifdef FEAT_MBYTE
  4850. /*
  4851.  * Insert bytes popped from the replace stack. "cc" is the first byte.  If it
  4852.  * indicates a multi-byte char, pop the other bytes too.
  4853.  */
  4854.     static void
  4855. mb_replace_pop_ins(cc)
  4856.     int        cc;
  4857. {
  4858.     int        n;
  4859.     char_u    buf[MB_MAXBYTES];
  4860.     int        i;
  4861.     int        c;
  4862.  
  4863.     if (has_mbyte && (n = MB_BYTE2LEN(cc)) > 1)
  4864.     {
  4865.     buf[0] = cc;
  4866.     for (i = 1; i < n; ++i)
  4867.         buf[i] = replace_pop();
  4868.     ins_bytes_len(buf, n);
  4869.     }
  4870.     else
  4871.     ins_char(cc);
  4872.  
  4873.     if (enc_utf8)
  4874.     /* Handle composing chars. */
  4875.     for (;;)
  4876.     {
  4877.         c = replace_pop();
  4878.         if (c == -1)        /* stack empty */
  4879.         break;
  4880.         if ((n = MB_BYTE2LEN(c)) == 1)
  4881.         {
  4882.         /* Not a multi-byte char, put it back. */
  4883.         replace_push(c);
  4884.         break;
  4885.         }
  4886.         else
  4887.         {
  4888.         buf[0] = c;
  4889.         for (i = 1; i < n; ++i)
  4890.             buf[i] = replace_pop();
  4891.         if (utf_iscomposing(utf_ptr2char(buf)))
  4892.             ins_bytes_len(buf, n);
  4893.         else
  4894.         {
  4895.             /* Not a composing char, put it back. */
  4896.             for (i = n - 1; i >= 0; --i)
  4897.             replace_push(buf[i]);
  4898.             break;
  4899.         }
  4900.         }
  4901.     }
  4902. }
  4903. #endif
  4904.  
  4905. /*
  4906.  * make the replace stack empty
  4907.  * (called when exiting replace mode)
  4908.  */
  4909.     static void
  4910. replace_flush()
  4911. {
  4912.     vim_free(replace_stack);
  4913.     replace_stack = NULL;
  4914.     replace_stack_len = 0;
  4915.     replace_stack_nr = 0;
  4916. }
  4917.  
  4918. /*
  4919.  * Handle doing a BS for one character.
  4920.  * cc < 0: replace stack empty, just move cursor
  4921.  * cc == 0: character was inserted, delete it
  4922.  * cc > 0: character was replaced, put cc (first byte of original char) back
  4923.  * and check for more characters to be put back
  4924.  */
  4925.     static void
  4926. replace_do_bs()
  4927. {
  4928.     int        cc;
  4929. #ifdef FEAT_VREPLACE
  4930.     int        orig_len = 0;
  4931.     int        ins_len;
  4932.     int        orig_vcols = 0;
  4933.     colnr_T    start_vcol;
  4934.     char_u    *p;
  4935.     int        i;
  4936.     int        vcol;
  4937. #endif
  4938.  
  4939.     cc = replace_pop();
  4940.     if (cc > 0)
  4941.     {
  4942. #ifdef FEAT_VREPLACE
  4943.     if (State & VREPLACE_FLAG)
  4944.     {
  4945.         /* Get the number of screen cells used by the character we are
  4946.          * going to delete. */
  4947.         getvcol(curwin, &curwin->w_cursor, NULL, &start_vcol, NULL);
  4948.         orig_vcols = chartabsize(ml_get_cursor(), start_vcol);
  4949.     }
  4950. #endif
  4951. #ifdef FEAT_MBYTE
  4952.     if (has_mbyte)
  4953.     {
  4954.         del_char(FALSE);
  4955. # ifdef FEAT_VREPLACE
  4956.         if (State & VREPLACE_FLAG)
  4957.         orig_len = STRLEN(ml_get_cursor());
  4958. # endif
  4959.         replace_push(cc);
  4960.     }
  4961.     else
  4962. #endif
  4963.     {
  4964.         pchar_cursor(cc);
  4965. #ifdef FEAT_VREPLACE
  4966.         if (State & VREPLACE_FLAG)
  4967.         orig_len = STRLEN(ml_get_cursor()) - 1;
  4968. #endif
  4969.     }
  4970.     replace_pop_ins();
  4971.  
  4972. #ifdef FEAT_VREPLACE
  4973.     if (State & VREPLACE_FLAG)
  4974.     {
  4975.         /* Get the number of screen cells used by the inserted characters */
  4976.         p = ml_get_cursor();
  4977.         ins_len = STRLEN(p) - orig_len;
  4978.         vcol = start_vcol;
  4979.         for (i = 0; i < ins_len; ++i)
  4980.         {
  4981.         vcol += chartabsize(p + i, vcol);
  4982. #ifdef FEAT_MBYTE
  4983.         i += (*mb_ptr2len_check)(p) - 1;
  4984. #endif
  4985.         }
  4986.         vcol -= start_vcol;
  4987.  
  4988.         /* Delete spaces that were inserted after the cursor to keep the
  4989.          * text aligned. */
  4990.         curwin->w_cursor.col += ins_len;
  4991.         while (vcol > orig_vcols && gchar_cursor() == ' ')
  4992.         {
  4993.         del_char(FALSE);
  4994.         ++orig_vcols;
  4995.         }
  4996.         curwin->w_cursor.col -= ins_len;
  4997.     }
  4998. #endif
  4999.  
  5000.     /* mark the buffer as changed and prepare for displaying */
  5001.     changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col);
  5002.     }
  5003.     else if (cc == 0)
  5004.     (void)del_char(FALSE);
  5005. }
  5006.  
  5007. #ifdef FEAT_CINDENT
  5008. /*
  5009.  * Return TRUE if C-indenting is on.
  5010.  */
  5011.     static int
  5012. cindent_on()
  5013. {
  5014.     return (!p_paste && (curbuf->b_p_cin
  5015. # ifdef FEAT_EVAL
  5016.             || *curbuf->b_p_inde != NUL
  5017. # endif
  5018.             ));
  5019. }
  5020. #endif
  5021.  
  5022. #if defined(FEAT_LISP) || defined(FEAT_CINDENT) || defined(PROTO)
  5023. /*
  5024.  * Re-indent the current line, based on the current contents of it and the
  5025.  * surrounding lines. Fixing the cursor position seems really easy -- I'm very
  5026.  * confused what all the part that handles Control-T is doing that I'm not.
  5027.  * "get_the_indent" should be get_c_indent, get_expr_indent or get_lisp_indent.
  5028.  */
  5029.  
  5030.     void
  5031. fixthisline(get_the_indent)
  5032.     int (*get_the_indent) __ARGS((void));
  5033. {
  5034.     change_indent(INDENT_SET, get_the_indent(), FALSE, 0);
  5035.     if (linewhite(curwin->w_cursor.lnum))
  5036.     did_ai = TRUE;        /* delete the indent if the line stays empty */
  5037. }
  5038.  
  5039.     void
  5040. fix_indent()
  5041. {
  5042.     if (p_paste)
  5043.     return;
  5044. # ifdef FEAT_LISP
  5045.     if (curbuf->b_p_lisp && curbuf->b_p_ai)
  5046.     fixthisline(get_lisp_indent);
  5047. # endif
  5048. # if defined(FEAT_LISP) && defined(FEAT_CINDENT)
  5049.     else
  5050. # endif
  5051. # ifdef FEAT_CINDENT
  5052.     if (cindent_on())
  5053.         do_c_expr_indent();
  5054. # endif
  5055. }
  5056.  
  5057. #endif
  5058.  
  5059. #ifdef FEAT_CINDENT
  5060. /*
  5061.  * return TRUE if 'cinkeys' contains the key "keytyped",
  5062.  * when == '*':        Only if key is preceded with '*'    (indent before insert)
  5063.  * when == '!':        Only if key is prededed with '!'    (don't insert)
  5064.  * when == ' ':        Only if key is not preceded with '*'(indent afterwards)
  5065.  *
  5066.  * "keytyped" can have a few special values:
  5067.  * KEY_OPEN_FORW
  5068.  * KEY_OPEN_BACK
  5069.  * KEY_COMPLETE        just finished completion.
  5070.  *
  5071.  * If line_is_empty is TRUE accept keys with '0' before them.
  5072.  */
  5073.     int
  5074. in_cinkeys(keytyped, when, line_is_empty)
  5075.     int        keytyped;
  5076.     int        when;
  5077.     int        line_is_empty;
  5078. {
  5079.     char_u    *look;
  5080.     int        try_match;
  5081.     int        try_match_word;
  5082.     char_u    *p;
  5083.     char_u    *line;
  5084.     int        icase;
  5085.     int        i;
  5086.  
  5087. #ifdef FEAT_EVAL
  5088.     if (*curbuf->b_p_inde != NUL)
  5089.     look = curbuf->b_p_indk;    /* 'indentexpr' set: use 'indentkeys' */
  5090.     else
  5091. #endif
  5092.     look = curbuf->b_p_cink;    /* 'indentexpr' empty: use 'cinkeys' */
  5093.     while (*look)
  5094.     {
  5095.     /*
  5096.      * Find out if we want to try a match with this key, depending on
  5097.      * 'when' and a '*' or '!' before the key.
  5098.      */
  5099.     switch (when)
  5100.     {
  5101.         case '*': try_match = (*look == '*'); break;
  5102.         case '!': try_match = (*look == '!'); break;
  5103.          default: try_match = (*look != '*'); break;
  5104.     }
  5105.     if (*look == '*' || *look == '!')
  5106.         ++look;
  5107.  
  5108.     /*
  5109.      * If there is a '0', only accept a match if the line is empty.
  5110.      * But may still match when typing last char of a word.
  5111.      */
  5112.     if (*look == '0')
  5113.     {
  5114.         try_match_word = try_match;
  5115.         if (!line_is_empty)
  5116.         try_match = FALSE;
  5117.         ++look;
  5118.     }
  5119.     else
  5120.         try_match_word = FALSE;
  5121.  
  5122.     /*
  5123.      * does it look like a control character?
  5124.      */
  5125.     if (*look == '^'
  5126. #ifdef EBCDIC
  5127.         && (Ctrl_chr(look[1]) != 0)
  5128. #else
  5129.         && look[1] >= '?' && look[1] <= '_'
  5130. #endif
  5131.         )
  5132.     {
  5133.         if (try_match && keytyped == Ctrl_chr(look[1]))
  5134.         return TRUE;
  5135.         look += 2;
  5136.     }
  5137.     /*
  5138.      * 'o' means "o" command, open forward.
  5139.      * 'O' means "O" command, open backward.
  5140.      */
  5141.     else if (*look == 'o')
  5142.     {
  5143.         if (try_match && keytyped == KEY_OPEN_FORW)
  5144.         return TRUE;
  5145.         ++look;
  5146.     }
  5147.     else if (*look == 'O')
  5148.     {
  5149.         if (try_match && keytyped == KEY_OPEN_BACK)
  5150.         return TRUE;
  5151.         ++look;
  5152.     }
  5153.  
  5154.     /*
  5155.      * 'e' means to check for "else" at start of line and just before the
  5156.      * cursor.
  5157.      */
  5158.     else if (*look == 'e')
  5159.     {
  5160.         if (try_match && keytyped == 'e' && curwin->w_cursor.col >= 4)
  5161.         {
  5162.         p = ml_get_curline();
  5163.         if (skipwhite(p) == p + curwin->w_cursor.col - 4 &&
  5164.             STRNCMP(p + curwin->w_cursor.col - 4, "else", 4) == 0)
  5165.             return TRUE;
  5166.         }
  5167.         ++look;
  5168.     }
  5169.  
  5170.     /*
  5171.      * ':' only causes an indent if it is at the end of a label or case
  5172.      * statement, or when it was before typing the ':' (to fix
  5173.      * class::method for C++).
  5174.      */
  5175.     else if (*look == ':')
  5176.     {
  5177.         if (try_match && keytyped == ':')
  5178.         {
  5179.         p = ml_get_curline();
  5180.         if (cin_iscase(p) || cin_isscopedecl(p) || cin_islabel(30))
  5181.             return TRUE;
  5182.         if (curwin->w_cursor.col > 2
  5183.             && p[curwin->w_cursor.col - 1] == ':'
  5184.             && p[curwin->w_cursor.col - 2] == ':')
  5185.         {
  5186.             p[curwin->w_cursor.col - 1] = ' ';
  5187.             i = (cin_iscase(p) || cin_isscopedecl(p)
  5188.                               || cin_islabel(30));
  5189.             p = ml_get_curline();
  5190.             p[curwin->w_cursor.col - 1] = ':';
  5191.             if (i)
  5192.             return TRUE;
  5193.         }
  5194.         }
  5195.         ++look;
  5196.     }
  5197.  
  5198.  
  5199.     /*
  5200.      * Is it a key in <>, maybe?
  5201.      */
  5202.     else if (*look == '<')
  5203.     {
  5204.         if (try_match)
  5205.         {
  5206.         /*
  5207.          * make up some named keys <o>, <O>, <e>, <0>, <>>, <<>, <*>,
  5208.          * <:> and <!> so that people can re-indent on o, O, e, 0, <,
  5209.          * >, *, : and ! keys if they really really want to.
  5210.          */
  5211.         if (vim_strchr((char_u *)"<>!*oOe0:", look[1]) != NULL
  5212.                                && keytyped == look[1])
  5213.             return TRUE;
  5214.  
  5215.         if (keytyped == get_special_key_code(look + 1))
  5216.             return TRUE;
  5217.         }
  5218.         while (*look && *look != '>')
  5219.         look++;
  5220.         while (*look == '>')
  5221.         look++;
  5222.     }
  5223.  
  5224.     /*
  5225.      * Is it a word: "=word"?
  5226.      */
  5227.     else if (*look == '=' && look[1] != ',' && look[1] != NUL)
  5228.     {
  5229.         ++look;
  5230.         if (*look == '~')
  5231.         {
  5232.         icase = TRUE;
  5233.         ++look;
  5234.         }
  5235.         else
  5236.         icase = FALSE;
  5237.         p = vim_strchr(look, ',');
  5238.         if (p == NULL)
  5239.         p = look + STRLEN(look);
  5240.         if ((try_match || try_match_word)
  5241.             && curwin->w_cursor.col >= (colnr_T)(p - look))
  5242.         {
  5243.         int        match = FALSE;
  5244.  
  5245. #ifdef FEAT_INS_EXPAND
  5246.         if (keytyped == KEY_COMPLETE)
  5247.         {
  5248.             char_u    *s;
  5249.  
  5250.             /* Just completed a word, check if it starts with "look".
  5251.              * search back for the start of a word. */
  5252.             line = ml_get_curline();
  5253. # ifdef FEAT_MBYTE
  5254.             if (has_mbyte)
  5255.             {
  5256.             char_u    *n;
  5257.  
  5258.             for (s = line + curwin->w_cursor.col; s > line; s = n)
  5259.             {
  5260.                 n = mb_prevptr(line, s);
  5261.                 if (!vim_iswordp(n))
  5262.                 break;
  5263.             }
  5264.             }
  5265.             else
  5266. # endif
  5267.             for (s = line + curwin->w_cursor.col; s > line; --s)
  5268.                 if (!vim_iswordc(s[-1]))
  5269.                 break;
  5270.             if (s + (p - look) <= line + curwin->w_cursor.col
  5271.                 && (icase
  5272.                 ? MB_STRNICMP(s, look, p - look)
  5273.                 : STRNCMP(s, look, p - look)) == 0)
  5274.             match = TRUE;
  5275.         }
  5276.         else
  5277. #endif
  5278.             /* TODO: multi-byte */
  5279.             if (keytyped == (int)p[-1])
  5280.         {
  5281.             line = ml_get_cursor();
  5282.             if ((curwin->w_cursor.col == (colnr_T)(p - look)
  5283.                 || !vim_iswordc(line[-(p - look) - 1]))
  5284.                 && (icase
  5285.                 ? MB_STRNICMP(line - (p - look), look, p - look)
  5286.                 : STRNCMP(line - (p - look), look, p - look))
  5287.                                      == 0)
  5288.             match = TRUE;
  5289.         }
  5290.         if (match && try_match_word && !try_match)
  5291.         {
  5292.             /* "0=word": Check if there are only blanks before the
  5293.              * word. */
  5294.             line = ml_get_curline();
  5295.             if ((int)(skipwhite(line) - line) !=
  5296.                      (int)(curwin->w_cursor.col - (p - look)))
  5297.             match = FALSE;
  5298.         }
  5299.         if (match)
  5300.             return TRUE;
  5301.         }
  5302.         look = p;
  5303.     }
  5304.  
  5305.     /*
  5306.      * ok, it's a boring generic character.
  5307.      */
  5308.     else
  5309.     {
  5310.         if (try_match && *look == keytyped)
  5311.         return TRUE;
  5312.         ++look;
  5313.     }
  5314.  
  5315.     /*
  5316.      * Skip over ", ".
  5317.      */
  5318.     look = skip_to_option_part(look);
  5319.     }
  5320.     return FALSE;
  5321. }
  5322. #endif /* FEAT_CINDENT */
  5323.  
  5324. #if defined(FEAT_RIGHTLEFT) || defined(PROTO)
  5325. /*
  5326.  * Map Hebrew keyboard when in hkmap mode.
  5327.  */
  5328.     int
  5329. hkmap(c)
  5330.     int c;
  5331. {
  5332.     if (p_hkmapp)   /* phonetic mapping, by Ilya Dogolazky */
  5333.     {
  5334.     enum {hALEF=0, BET, GIMEL, DALET, HEI, VAV, ZAIN, HET, TET, IUD,
  5335.         KAFsofit, hKAF, LAMED, MEMsofit, MEM, NUNsofit, NUN, SAMEH, AIN,
  5336.         PEIsofit, PEI, ZADIsofit, ZADI, KOF, RESH, hSHIN, TAV};
  5337.     static char_u map[26] =
  5338.         {(char_u)hALEF/*a*/, (char_u)BET  /*b*/, (char_u)hKAF    /*c*/,
  5339.          (char_u)DALET/*d*/, (char_u)-1   /*e*/, (char_u)PEIsofit/*f*/,
  5340.          (char_u)GIMEL/*g*/, (char_u)HEI  /*h*/, (char_u)IUD     /*i*/,
  5341.          (char_u)HET  /*j*/, (char_u)KOF  /*k*/, (char_u)LAMED   /*l*/,
  5342.          (char_u)MEM  /*m*/, (char_u)NUN  /*n*/, (char_u)SAMEH   /*o*/,
  5343.          (char_u)PEI  /*p*/, (char_u)-1   /*q*/, (char_u)RESH    /*r*/,
  5344.          (char_u)ZAIN /*s*/, (char_u)TAV  /*t*/, (char_u)TET     /*u*/,
  5345.          (char_u)VAV  /*v*/, (char_u)hSHIN/*w*/, (char_u)-1      /*x*/,
  5346.          (char_u)AIN  /*y*/, (char_u)ZADI /*z*/};
  5347.  
  5348.     if (c == 'N' || c == 'M' || c == 'P' || c == 'C' || c == 'Z')
  5349.         return (int)(map[CharOrd(c)] - 1 + p_aleph);
  5350.                                 /* '-1'='sofit' */
  5351.     else if (c == 'x')
  5352.         return 'X';
  5353.     else if (c == 'q')
  5354.         return '\''; /* {geresh}={'} */
  5355.     else if (c == 246)
  5356.         return ' ';  /* \"o --> ' ' for a german keyboard */
  5357.     else if (c == 228)
  5358.         return ' ';  /* \"a --> ' '      -- / --           */
  5359.     else if (c == 252)
  5360.         return ' ';  /* \"u --> ' '      -- / --           */
  5361. #ifdef EBCDIC
  5362.     else if (islower(c))
  5363. #else
  5364.     /* NOTE: islower() does not do the right thing for us on Linux so we
  5365.      * do this the same was as 5.7 and previous, so it works correctly on
  5366.      * all systems.  Specifically, the e.g. Delete and Arrow keys are
  5367.      * munged and won't work if e.g. searching for Hebrew text.
  5368.      */
  5369.     else if (c >= 'a' && c <= 'z')
  5370. #endif
  5371.         return (int)(map[CharOrdLow(c)] + p_aleph);
  5372.     else
  5373.         return c;
  5374.     }
  5375.     else
  5376.     {
  5377.     switch (c)
  5378.     {
  5379.         case '`':    return ';';
  5380.         case '/':    return '.';
  5381.         case '\'':    return ',';
  5382.         case 'q':    return '/';
  5383.         case 'w':    return '\'';
  5384.  
  5385.             /* Hebrew letters - set offset from 'a' */
  5386.         case ',':    c = '{'; break;
  5387.         case '.':    c = 'v'; break;
  5388.         case ';':    c = 't'; break;
  5389.         default: {
  5390.              static char str[] = "zqbcxlsjphmkwonu ydafe rig";
  5391.  
  5392. #ifdef EBCDIC
  5393.              /* see note about islower() above */
  5394.              if (!islower(c))
  5395. #else
  5396.              if (c < 'a' || c > 'z')
  5397. #endif
  5398.                  return c;
  5399.              c = str[CharOrdLow(c)];
  5400.              break;
  5401.              }
  5402.     }
  5403.  
  5404.     return (int)(CharOrdLow(c) + p_aleph);
  5405.     }
  5406. }
  5407. #endif
  5408.  
  5409.     static void
  5410. ins_reg()
  5411. {
  5412.     int        need_redraw = FALSE;
  5413.     int        regname;
  5414.     int        literally = 0;
  5415.  
  5416.     /*
  5417.      * If we are going to wait for a character, show a '"'.
  5418.      */
  5419.     if (redrawing() && !char_avail())
  5420.     {
  5421.     /* may need to redraw when no more chars available now */
  5422.     ins_redraw();
  5423.  
  5424.     edit_putchar('"', TRUE);
  5425. #ifdef FEAT_CMDL_INFO
  5426.     add_to_showcmd_c(Ctrl_R);
  5427. #endif
  5428.     }
  5429.  
  5430. #ifdef USE_ON_FLY_SCROLL
  5431.     dont_scroll = TRUE;        /* disallow scrolling here */
  5432. #endif
  5433.  
  5434.     /*
  5435.      * Don't map the register name. This also prevents the mode message to be
  5436.      * deleted when ESC is hit.
  5437.      */
  5438.     ++no_mapping;
  5439.     regname = safe_vgetc();
  5440. #ifdef FEAT_LANGMAP
  5441.     LANGMAP_ADJUST(regname, TRUE);
  5442. #endif
  5443.     if (regname == Ctrl_R || regname == Ctrl_O || regname == Ctrl_P)
  5444.     {
  5445.     /* Get a third key for literal register insertion */
  5446.     literally = regname;
  5447. #ifdef FEAT_CMDL_INFO
  5448.     add_to_showcmd_c(literally);
  5449. #endif
  5450.     regname = safe_vgetc();
  5451. #ifdef FEAT_LANGMAP
  5452.     LANGMAP_ADJUST(regname, TRUE);
  5453. #endif
  5454.     }
  5455.     --no_mapping;
  5456.  
  5457. #ifdef FEAT_EVAL
  5458.     /*
  5459.      * Don't call u_sync() while getting the expression,
  5460.      * evaluating it or giving an error message for it!
  5461.      */
  5462.     ++no_u_sync;
  5463.     if (regname == '=')
  5464.     {
  5465. #ifdef USE_IM_CONTROL
  5466.     int    im_on = im_get_status();
  5467. #endif
  5468.     regname = get_expr_register();
  5469. #ifdef USE_IM_CONTROL
  5470.     /* Restore the Input Method. */
  5471.     if (im_on)
  5472.         im_set_active(TRUE);
  5473. #endif
  5474.     }
  5475.     if (regname == NUL)
  5476.     need_redraw = TRUE;    /* remove the '"' */
  5477.     else
  5478.     {
  5479. #endif
  5480.     if (literally == Ctrl_O || literally == Ctrl_P)
  5481.     {
  5482.         /* Append the command to the redo buffer. */
  5483.         AppendCharToRedobuff(Ctrl_R);
  5484.         AppendCharToRedobuff(literally);
  5485.         AppendCharToRedobuff(regname);
  5486.  
  5487.         do_put(regname, BACKWARD, 1L,
  5488.          (literally == Ctrl_P ? PUT_FIXINDENT : 0) | PUT_CURSEND);
  5489.     }
  5490.     else if (insert_reg(regname, literally) == FAIL)
  5491.     {
  5492.         vim_beep();
  5493.         need_redraw = TRUE;    /* remove the '"' */
  5494.     }
  5495. #ifdef FEAT_EVAL
  5496.     }
  5497.     --no_u_sync;
  5498. #endif
  5499. #ifdef FEAT_CMDL_INFO
  5500.     clear_showcmd();
  5501. #endif
  5502.  
  5503.     /* If the inserted register is empty, we need to remove the '"' */
  5504.     if (need_redraw || stuff_empty())
  5505.     edit_unputchar();
  5506. }
  5507.  
  5508. /*
  5509.  * CTRL-G commands in Insert mode.
  5510.  */
  5511.     static void
  5512. ins_ctrl_g()
  5513. {
  5514.     int        c;
  5515.  
  5516.     /*
  5517.      * Don't map the register name. This also prevents the mode message to be
  5518.      * deleted when ESC is hit.
  5519.      */
  5520.     ++no_mapping;
  5521.     c = safe_vgetc();
  5522.     --no_mapping;
  5523.     switch (c)
  5524.     {
  5525.     /* CTRL-G k and CTRL-G <Up>: cursor up to Insstart.col */
  5526.     case K_UP:
  5527.     case Ctrl_K:
  5528.     case 'k': ins_up(TRUE);
  5529.           break;
  5530.  
  5531.     /* CTRL-G j and CTRL-G <Down>: cursor down to Insstart.col */
  5532.     case K_DOWN:
  5533.     case Ctrl_J:
  5534.     case 'j': ins_down(TRUE);
  5535.           break;
  5536.  
  5537.     /* Unknown CTRL-G command, reserved for future expansion. */
  5538.     default:  vim_beep();
  5539.     }
  5540. }
  5541.  
  5542. /*
  5543.  * Handle ESC in insert mode.
  5544.  * Returns TRUE when leaving insert mode, FALSE when going to repeat the
  5545.  * insert.
  5546.  */
  5547.     static int
  5548. ins_esc(count, cmdchar)
  5549.     long    *count;
  5550.     int        cmdchar;
  5551. {
  5552.     int        temp;
  5553.     static int    disabled_redraw = FALSE;
  5554.  
  5555. #if defined(FEAT_HANGULIN)
  5556. # if defined(ESC_CHG_TO_ENG_MODE)
  5557.     hangul_input_state_set(0);
  5558. # endif
  5559.     if (composing_hangul)
  5560.     {
  5561.     push_raw_key(composing_hangul_buffer, 2);
  5562.     composing_hangul = 0;
  5563.     }
  5564. #endif
  5565. #if defined(FEAT_MBYTE) && defined(MACOS)
  5566.     previous_script = GetScriptManagerVariable(smKeyScript);
  5567.     KeyScript(smKeyRoman); /* or smKeySysScript */
  5568. #endif
  5569.  
  5570.     temp = curwin->w_cursor.col;
  5571.     if (disabled_redraw)
  5572.     {
  5573.     --RedrawingDisabled;
  5574.     disabled_redraw = FALSE;
  5575.     }
  5576.     if (!arrow_used)
  5577.     {
  5578.     /*
  5579.      * Don't append the ESC for "r<CR>".
  5580.      */
  5581.     if (cmdchar != 'r' && cmdchar != 'v')
  5582.         AppendToRedobuff(ESC_STR);
  5583.  
  5584.     /*
  5585.      * Repeating insert may take a long time.  Check for
  5586.      * interrupt now and then.
  5587.      */
  5588.     if (*count)
  5589.     {
  5590.         line_breakcheck();
  5591.         if (got_int)
  5592.         *count = 0;
  5593.     }
  5594.  
  5595.     if (--*count > 0)    /* repeat what was typed */
  5596.     {
  5597.         (void)start_redo_ins();
  5598.         ++RedrawingDisabled;
  5599.         disabled_redraw = TRUE;
  5600.         return FALSE;    /* repeat the insert */
  5601.     }
  5602.     stop_insert(&curwin->w_cursor);
  5603.     undisplay_dollar();
  5604.     }
  5605.  
  5606.     /* When an autoindent was removed, curswant stays after the
  5607.      * indent */
  5608.     if (restart_edit == NUL && (colnr_T)temp == curwin->w_cursor.col)
  5609.     curwin->w_set_curswant = TRUE;
  5610.  
  5611.     /* Remember the last Insert position in the '^ mark. */
  5612.     curbuf->b_last_insert = curwin->w_cursor;
  5613.  
  5614.     /*
  5615.      * The cursor should end up on the last inserted character.
  5616.      */
  5617.     if ((curwin->w_cursor.col != 0
  5618. #ifdef FEAT_VIRTUALEDIT
  5619.         || curwin->w_cursor.coladd > 0
  5620. #endif
  5621.     ) && (restart_edit == NUL
  5622.         || (gchar_cursor() == NUL
  5623. #ifdef FEAT_VISUAL
  5624.             && !VIsual_active
  5625. #endif
  5626.             ))
  5627. #ifdef FEAT_RIGHTLEFT
  5628.         && !revins_on
  5629. #endif
  5630.                       )
  5631.     {
  5632. #ifdef FEAT_VIRTUALEDIT
  5633.     if (curwin->w_cursor.coladd > 0 || ve_flags == VE_ALL)
  5634.         oneleft();
  5635.     else
  5636. #endif
  5637.         --curwin->w_cursor.col;
  5638.     }
  5639.  
  5640.     State = NORMAL;
  5641.     /* need to position cursor again (e.g. when on a TAB ) */
  5642.     changed_cline_bef_curs();
  5643.  
  5644. #ifdef FEAT_MOUSE
  5645.     setmouse();
  5646. #endif
  5647. #ifdef CURSOR_SHAPE
  5648.     ui_cursor_shape();        /* may show different cursor shape */
  5649. #endif
  5650.  
  5651. #ifdef USE_IM_CONTROL
  5652.     /* Disable IM to allow typing English directly for Normal mode commands. */
  5653.     im_save_status(&curbuf->b_p_iminsert);
  5654.     im_set_active(FALSE);
  5655. #endif
  5656.  
  5657.     /*
  5658.      * When recording or for CTRL-O, need to display the new mode.
  5659.      * Otherwise remove the mode message.
  5660.      */
  5661.     if (Recording || restart_edit != NUL)
  5662.     showmode();
  5663.     else if (p_smd)
  5664.     MSG("");
  5665.  
  5666.     return TRUE;        /* exit Insert mode */
  5667. }
  5668.  
  5669. #ifdef FEAT_RIGHTLEFT
  5670. /*
  5671.  * Toggle language: hkmap and revins_on.
  5672.  * Move to end of reverse inserted text.
  5673.  */
  5674.     static void
  5675. ins_ctrl_()
  5676. {
  5677.     if (revins_on && revins_chars && revins_scol >= 0)
  5678.     {
  5679.     while (gchar_cursor() != NUL && revins_chars--)
  5680.         ++curwin->w_cursor.col;
  5681.     }
  5682.     p_ri = !p_ri;
  5683.     revins_on = (State == INSERT && p_ri);
  5684.     if (revins_on)
  5685.     {
  5686.     revins_scol = curwin->w_cursor.col;
  5687.     revins_legal++;
  5688.     revins_chars = 0;
  5689.     undisplay_dollar();
  5690.     }
  5691.     else
  5692.     revins_scol = -1;
  5693. #ifdef FEAT_FKMAP
  5694.     if (p_altkeymap)
  5695.     {
  5696.     /*
  5697.      * to be consistent also for redo command, using '.'
  5698.      * set arrow_used to true and stop it - causing to redo
  5699.      * characters entered in one mode (normal/reverse insert).
  5700.      */
  5701.     arrow_used = TRUE;
  5702.     (void)stop_arrow();
  5703.     p_fkmap = curwin->w_p_rl ^ p_ri;
  5704.     if (p_fkmap && p_ri)
  5705.         State = INSERT;
  5706.     }
  5707.     else
  5708. #endif
  5709.     p_hkmap = curwin->w_p_rl ^ p_ri;    /* be consistent! */
  5710.     showmode();
  5711. }
  5712. #endif
  5713.  
  5714. #ifdef FEAT_VISUAL
  5715. /*
  5716.  * If 'keymodel' contains "startsel", may start selection.
  5717.  * Returns TRUE when a CTRL-O and other keys stuffed.
  5718.  */
  5719.     static int
  5720. ins_start_select(c)
  5721.     int        c;
  5722. {
  5723.     if (km_startsel)
  5724.     switch (c)
  5725.     {
  5726.         case K_KHOME:
  5727.         case K_XHOME:
  5728.         case K_KEND:
  5729.         case K_XEND:
  5730.         case K_PAGEUP:
  5731.         case K_KPAGEUP:
  5732.         case K_PAGEDOWN:
  5733.         case K_KPAGEDOWN:
  5734. # ifdef MACOS
  5735.         case K_LEFT:
  5736.         case K_RIGHT:
  5737.         case K_UP:
  5738.         case K_DOWN:
  5739.         case K_END:
  5740.         case K_HOME:
  5741. # endif
  5742.         if (!(mod_mask & MOD_MASK_SHIFT))
  5743.             break;
  5744.         /* FALLTHROUGH */
  5745.         case K_S_LEFT:
  5746.         case K_S_RIGHT:
  5747.         case K_S_UP:
  5748.         case K_S_DOWN:
  5749.         case K_S_END:
  5750.         case K_S_HOME:
  5751.         /* Start selection right away, the cursor can move with
  5752.          * CTRL-O when beyond the end of the line. */
  5753.         start_selection();
  5754.  
  5755.         /* Execute the key in (insert) Select mode, unless it's
  5756.          * shift-left and beyond the end of the line (the CTRL-O
  5757.          * will move the cursor left already). */
  5758.         stuffcharReadbuff(Ctrl_O);
  5759.         if (c != K_S_LEFT || gchar_cursor() != NUL)
  5760.         {
  5761.             if (mod_mask)
  5762.             {
  5763.             char_u        buf[4];
  5764.  
  5765.             buf[0] = K_SPECIAL;
  5766.             buf[1] = KS_MODIFIER;
  5767.             buf[2] = mod_mask;
  5768.             buf[3] = NUL;
  5769.             stuffReadbuff(buf);
  5770.             }
  5771.             stuffcharReadbuff(c);
  5772.         }
  5773.         return TRUE;
  5774.     }
  5775.     return FALSE;
  5776. }
  5777. #endif
  5778.  
  5779. /*
  5780.  * If the cursor is on an indent, ^T/^D insert/delete one
  5781.  * shiftwidth.    Otherwise ^T/^D behave like a "<<" or ">>".
  5782.  * Always round the indent to 'shiftwith', this is compatible
  5783.  * with vi.  But vi only supports ^T and ^D after an
  5784.  * autoindent, we support it everywhere.
  5785.  */
  5786.     static void
  5787. ins_shift(c, lastc)
  5788.     int        c;
  5789.     int        lastc;
  5790. {
  5791.     if (stop_arrow() == FAIL)
  5792.     return;
  5793.     AppendCharToRedobuff(c);
  5794.  
  5795.     /*
  5796.      * 0^D and ^^D: remove all indent.
  5797.      */
  5798.     if ((lastc == '0' || lastc == '^') && curwin->w_cursor.col)
  5799.     {
  5800.     --curwin->w_cursor.col;
  5801.     (void)del_char(FALSE);        /* delete the '^' or '0' */
  5802.     /* In Replace mode, restore the characters that '^' or '0' replaced. */
  5803.     if (State & REPLACE_FLAG)
  5804.         replace_pop_ins();
  5805.     if (lastc == '^')
  5806.         old_indent = get_indent();    /* remember curr. indent */
  5807.     change_indent(INDENT_SET, 0, TRUE, 0);
  5808.     }
  5809.     else
  5810.     change_indent(c == Ctrl_D ? INDENT_DEC : INDENT_INC, 0, TRUE, 0);
  5811.  
  5812.     if (did_ai && *skipwhite(ml_get_curline()) != NUL)
  5813.     did_ai = FALSE;
  5814. #ifdef FEAT_SMARTINDENT
  5815.     did_si = FALSE;
  5816.     can_si = FALSE;
  5817.     can_si_back = FALSE;
  5818. #endif
  5819. #ifdef FEAT_CINDENT
  5820.     can_cindent = FALSE;    /* no cindenting after ^D or ^T */
  5821. #endif
  5822. }
  5823.  
  5824.     static void
  5825. ins_del()
  5826. {
  5827.     int        temp;
  5828.  
  5829.     if (stop_arrow() == FAIL)
  5830.     return;
  5831.     if (gchar_cursor() == NUL)        /* delete newline */
  5832.     {
  5833.     temp = curwin->w_cursor.col;
  5834.     if (!can_bs(BS_EOL)        /* only if "eol" included */
  5835.         || u_save((linenr_T)(curwin->w_cursor.lnum - 1),
  5836.             (linenr_T)(curwin->w_cursor.lnum + 2)) == FAIL
  5837.         || do_join(FALSE) == FAIL)
  5838.         vim_beep();
  5839.     else
  5840.         curwin->w_cursor.col = temp;
  5841.     }
  5842.     else if (del_char(FALSE) == FAIL)    /* delete char under cursor */
  5843.     vim_beep();
  5844.     did_ai = FALSE;
  5845. #ifdef FEAT_SMARTINDENT
  5846.     did_si = FALSE;
  5847.     can_si = FALSE;
  5848.     can_si_back = FALSE;
  5849. #endif
  5850.     AppendCharToRedobuff(K_DEL);
  5851. }
  5852.  
  5853. /*
  5854.  * Handle Backspace, delete-word and delete-line in Insert mode.
  5855.  * Return TRUE when backspace was actually used.
  5856.  */
  5857.     static int
  5858. ins_bs(c, mode, inserted_space_p)
  5859.     int        c;
  5860.     int        mode;
  5861.     int        *inserted_space_p;
  5862. {
  5863.     linenr_T    lnum;
  5864.     int        cc;
  5865.     int        temp = 0;        /* init for GCC */
  5866.     colnr_T    mincol;
  5867.     int        did_backspace = FALSE;
  5868.     int        in_indent;
  5869.     int        oldState;
  5870. #ifdef FEAT_MBYTE
  5871.     int        p1, p2;
  5872. #endif
  5873.  
  5874.     /*
  5875.      * can't delete anything in an empty file
  5876.      * can't backup past first character in buffer
  5877.      * can't backup past starting point unless 'backspace' > 1
  5878.      * can backup to a previous line if 'backspace' == 0
  5879.      */
  5880.     if (       bufempty()
  5881.         || (
  5882. #ifdef FEAT_RIGHTLEFT
  5883.         !revins_on &&
  5884. #endif
  5885.         ((curwin->w_cursor.lnum == 1 && curwin->w_cursor.col == 0)
  5886.             || (!can_bs(BS_START)
  5887.             && (arrow_used
  5888.                 || (curwin->w_cursor.lnum == Insstart.lnum
  5889.                 && curwin->w_cursor.col <= Insstart.col)))
  5890.             || (!can_bs(BS_INDENT) && !arrow_used && ai_col > 0
  5891.                      && curwin->w_cursor.col <= ai_col)
  5892.             || (!can_bs(BS_EOL) && curwin->w_cursor.col == 0))))
  5893.     {
  5894.     vim_beep();
  5895.     return FALSE;
  5896.     }
  5897.  
  5898.     if (stop_arrow() == FAIL)
  5899.     return FALSE;
  5900.     in_indent = inindent(0);
  5901. #ifdef FEAT_CINDENT
  5902.     if (in_indent)
  5903.     can_cindent = FALSE;
  5904. #endif
  5905. #ifdef FEAT_COMMENTS
  5906.     end_comment_pending = NUL;    /* After BS, don't auto-end comment */
  5907. #endif
  5908. #ifdef FEAT_RIGHTLEFT
  5909.     if (revins_on)        /* put cursor after last inserted char */
  5910.     inc_cursor();
  5911. #endif
  5912.  
  5913. #ifdef FEAT_VIRTUALEDIT
  5914.     /* Virtualedit:
  5915.      *    BACKSPACE_CHAR eats a virtual space
  5916.      *    BACKSPACE_WORD eats all coladd
  5917.      *    BACKSPACE_LINE eats all coladd and keeps going
  5918.      */
  5919.     if (curwin->w_cursor.coladd > 0)
  5920.     {
  5921.     if (mode == BACKSPACE_CHAR)
  5922.     {
  5923.         --curwin->w_cursor.coladd;
  5924.         return TRUE;
  5925.     }
  5926.     if (mode == BACKSPACE_WORD)
  5927.     {
  5928.         curwin->w_cursor.coladd = 0;
  5929.         return TRUE;
  5930.     }
  5931.     curwin->w_cursor.coladd = 0;
  5932.     }
  5933. #endif
  5934.  
  5935.     /*
  5936.      * delete newline!
  5937.      */
  5938.     if (curwin->w_cursor.col == 0)
  5939.     {
  5940.     lnum = Insstart.lnum;
  5941.     if (curwin->w_cursor.lnum == Insstart.lnum
  5942. #ifdef FEAT_RIGHTLEFT
  5943.             || revins_on
  5944. #endif
  5945.                     )
  5946.     {
  5947.         if (u_save((linenr_T)(curwin->w_cursor.lnum - 2),
  5948.                    (linenr_T)(curwin->w_cursor.lnum + 1)) == FAIL)
  5949.         return FALSE;
  5950.         --Insstart.lnum;
  5951.         Insstart.col = MAXCOL;
  5952.     }
  5953.     /*
  5954.      * In replace mode:
  5955.      * cc < 0: NL was inserted, delete it
  5956.      * cc >= 0: NL was replaced, put original characters back
  5957.      */
  5958.     cc = -1;
  5959.     if (State & REPLACE_FLAG)
  5960.         cc = replace_pop();        /* returns -1 if NL was inserted */
  5961.     /*
  5962.      * In replace mode, in the line we started replacing, we only move the
  5963.      * cursor.
  5964.      */
  5965.     if ((State & REPLACE_FLAG) && curwin->w_cursor.lnum <= lnum)
  5966.     {
  5967.         dec_cursor();
  5968.     }
  5969.     else
  5970.     {
  5971. #ifdef FEAT_VREPLACE
  5972.         if (!(State & VREPLACE_FLAG)
  5973.                    || curwin->w_cursor.lnum > orig_line_count)
  5974. #endif
  5975.         {
  5976.         temp = gchar_cursor();    /* remember current char */
  5977.         --curwin->w_cursor.lnum;
  5978.         (void)do_join(FALSE);
  5979.         if (temp == NUL && gchar_cursor() != NUL)
  5980.             inc_cursor();
  5981.         }
  5982. #ifdef FEAT_VREPLACE
  5983.         else
  5984.         dec_cursor();
  5985. #endif
  5986.  
  5987.         /*
  5988.          * In REPLACE mode we have to put back the text that was replaced
  5989.          * by the NL. On the replace stack is first a NUL-terminated
  5990.          * sequence of characters that were deleted and then the
  5991.          * characters that NL replaced.
  5992.          */
  5993.         if (State & REPLACE_FLAG)
  5994.         {
  5995.         /*
  5996.          * Do the next ins_char() in NORMAL state, to
  5997.          * prevent ins_char() from replacing characters and
  5998.          * avoiding showmatch().
  5999.          */
  6000.         oldState = State;
  6001.         State = NORMAL;
  6002.         /*
  6003.          * restore characters (blanks) deleted after cursor
  6004.          */
  6005.         while (cc > 0)
  6006.         {
  6007.             temp = curwin->w_cursor.col;
  6008. #ifdef FEAT_MBYTE
  6009.             mb_replace_pop_ins(cc);
  6010. #else
  6011.             ins_char(cc);
  6012. #endif
  6013.             curwin->w_cursor.col = temp;
  6014.             cc = replace_pop();
  6015.         }
  6016.         /* restore the characters that NL replaced */
  6017.         replace_pop_ins();
  6018.         State = oldState;
  6019.         }
  6020.     }
  6021.     did_ai = FALSE;
  6022.     }
  6023.     else
  6024.     {
  6025.     /*
  6026.      * Delete character(s) before the cursor.
  6027.      */
  6028. #ifdef FEAT_RIGHTLEFT
  6029.     if (revins_on)        /* put cursor on last inserted char */
  6030.         dec_cursor();
  6031. #endif
  6032.     mincol = 0;
  6033.                         /* keep indent */
  6034.     if (mode == BACKSPACE_LINE && curbuf->b_p_ai
  6035. #ifdef FEAT_RIGHTLEFT
  6036.         && !revins_on
  6037. #endif
  6038.                 )
  6039.     {
  6040.         temp = curwin->w_cursor.col;
  6041.         beginline(BL_WHITE);
  6042.         if (curwin->w_cursor.col < (colnr_T)temp)
  6043.         mincol = curwin->w_cursor.col;
  6044.         curwin->w_cursor.col = temp;
  6045.     }
  6046.  
  6047.     /*
  6048.      * Handle deleting one 'shiftwidth' or 'softtabstop'.
  6049.      */
  6050.     if (       mode == BACKSPACE_CHAR
  6051.         && ((p_sta && in_indent)
  6052.             || (curbuf->b_p_sts
  6053.             && (*(ml_get_cursor() - 1) == TAB
  6054.                 || (*(ml_get_cursor() - 1) == ' '
  6055.                 && (!*inserted_space_p
  6056.                     || arrow_used))))))
  6057.     {
  6058.         int        ts;
  6059.         colnr_T    vcol;
  6060.         colnr_T    want_vcol;
  6061.         int        extra = 0;
  6062.  
  6063.         *inserted_space_p = FALSE;
  6064.         if (p_sta)
  6065.         ts = curbuf->b_p_sw;
  6066.         else
  6067.         ts = curbuf->b_p_sts;
  6068.         /* Compute the virtual column where we want to be.  Since
  6069.          * 'showbreak' may get in the way, need to get the last column of
  6070.          * the previous character. */
  6071.         getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
  6072.         dec_cursor();
  6073.         getvcol(curwin, &curwin->w_cursor, NULL, NULL, &want_vcol);
  6074.         inc_cursor();
  6075.         want_vcol = (want_vcol / ts) * ts;
  6076.  
  6077.         /* delete characters until we are at or before want_vcol */
  6078.         while ((int)vcol > want_vcol
  6079.             && (cc = *(ml_get_cursor() - 1), vim_iswhite(cc)))
  6080.         {
  6081.         dec_cursor();
  6082.         getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
  6083.         if (State & REPLACE_FLAG)
  6084.         {
  6085.             /* Don't delete characters before the insert point when in
  6086.              * Replace mode */
  6087.             if (curwin->w_cursor.lnum != Insstart.lnum
  6088.                 || curwin->w_cursor.col >= Insstart.col)
  6089.             {
  6090. #if 0    /* what was this for?  It causes problems when sw != ts. */
  6091.             if (State == REPLACE && (int)vcol < want_vcol)
  6092.             {
  6093.                 (void)del_char(FALSE);
  6094.                 extra = 2;    /* don't pop too much */
  6095.             }
  6096.             else
  6097. #endif
  6098.                 replace_do_bs();
  6099.             }
  6100.         }
  6101.         else
  6102.             (void)del_char(FALSE);
  6103.         }
  6104.  
  6105.         /* insert extra spaces until we are at want_vcol */
  6106.         while ((int)vcol < want_vcol)
  6107.         {
  6108.         /* Remember the first char we inserted */
  6109.         if (curwin->w_cursor.lnum == Insstart.lnum
  6110.                    && curwin->w_cursor.col < Insstart.col)
  6111.             Insstart.col = curwin->w_cursor.col;
  6112.  
  6113. #ifdef FEAT_VREPLACE
  6114.         if (State & VREPLACE_FLAG)
  6115.             ins_char(' ');
  6116.         else
  6117. #endif
  6118.         {
  6119.             ins_str((char_u *)" ");
  6120.             if ((State & REPLACE_FLAG) && extra <= 1)
  6121.             {
  6122.             if (extra)
  6123.                 replace_push_off(NUL);
  6124.             else
  6125.                 replace_push(NUL);
  6126.             }
  6127.             if (extra == 2)
  6128.             extra = 1;
  6129.         }
  6130.         getvcol(curwin, &curwin->w_cursor, &vcol, NULL, NULL);
  6131.         }
  6132.     }
  6133.  
  6134.     /*
  6135.      * Delete upto starting point, start of line or previous word.
  6136.      */
  6137.     else do
  6138.     {
  6139. #ifdef FEAT_RIGHTLEFT
  6140.         if (!revins_on) /* put cursor on char to be deleted */
  6141. #endif
  6142.         dec_cursor();
  6143.  
  6144.         /* start of word? */
  6145.         if (mode == BACKSPACE_WORD && !vim_isspace(gchar_cursor()))
  6146.         {
  6147.         mode = BACKSPACE_WORD_NOT_SPACE;
  6148.         temp = vim_iswordc(gchar_cursor());
  6149.         }
  6150.         /* end of word? */
  6151.         else if (mode == BACKSPACE_WORD_NOT_SPACE
  6152.             && (vim_isspace(cc = gchar_cursor())
  6153.                 || vim_iswordc(cc) != temp))
  6154.         {
  6155. #ifdef FEAT_RIGHTLEFT
  6156.         if (!revins_on)
  6157. #endif
  6158.             inc_cursor();
  6159. #ifdef FEAT_RIGHTLEFT
  6160.         else if (State & REPLACE_FLAG)
  6161.             dec_cursor();
  6162. #endif
  6163.         break;
  6164.         }
  6165.         if (State & REPLACE_FLAG)
  6166.         replace_do_bs();
  6167.         else
  6168.         {
  6169. #ifdef FEAT_MBYTE
  6170.         if (enc_utf8 && p_deco)
  6171.             utfc_ptr2char(ml_get_cursor(), &p1, &p2);
  6172. #endif
  6173.         (void)del_char(FALSE);
  6174. #ifdef FEAT_MBYTE
  6175.         /*
  6176.          * If p1 or p2 is non-zero, there are combining characters we
  6177.          * need to take account of.  Don't back up before the base
  6178.          * character.
  6179.          */
  6180.         if (enc_utf8 && p_deco && (p1 != NUL || p2 != NUL))
  6181.             inc_cursor();
  6182. #endif
  6183. #ifdef FEAT_RIGHTLEFT
  6184.         if (revins_chars)
  6185.         {
  6186.             revins_chars--;
  6187.             revins_legal++;
  6188.         }
  6189.         if (revins_on && gchar_cursor() == NUL)
  6190.             break;
  6191. #endif
  6192.         }
  6193.         /* Just a single backspace?: */
  6194.         if (mode == BACKSPACE_CHAR)
  6195.         break;
  6196.     } while (
  6197. #ifdef FEAT_RIGHTLEFT
  6198.         revins_on ||
  6199. #endif
  6200.         (curwin->w_cursor.col > mincol
  6201.          && (curwin->w_cursor.lnum != Insstart.lnum
  6202.              || curwin->w_cursor.col != Insstart.col)));
  6203.     did_backspace = TRUE;
  6204.     }
  6205. #ifdef FEAT_SMARTINDENT
  6206.     did_si = FALSE;
  6207.     can_si = FALSE;
  6208.     can_si_back = FALSE;
  6209. #endif
  6210.     if (curwin->w_cursor.col <= 1)
  6211.     did_ai = FALSE;
  6212.     /*
  6213.      * It's a little strange to put backspaces into the redo
  6214.      * buffer, but it makes auto-indent a lot easier to deal
  6215.      * with.
  6216.      */
  6217.     AppendCharToRedobuff(c);
  6218.  
  6219.     /* If deleted before the insertion point, adjust it */
  6220.     if (curwin->w_cursor.lnum == Insstart.lnum
  6221.                        && curwin->w_cursor.col < Insstart.col)
  6222.     Insstart.col = curwin->w_cursor.col;
  6223.  
  6224.     return did_backspace;
  6225. }
  6226.  
  6227. #ifdef FEAT_MOUSE
  6228.     static void
  6229. ins_mouse(c)
  6230.     int        c;
  6231. {
  6232.     pos_T    tpos;
  6233.  
  6234. # ifdef FEAT_GUI
  6235.     /* When GUI is active, also move/paste when 'mouse' is empty */
  6236.     if (!gui.in_use)
  6237. # endif
  6238.     if (!mouse_has(MOUSE_INSERT))
  6239.         return;
  6240.  
  6241.     undisplay_dollar();
  6242.     tpos = curwin->w_cursor;
  6243.     if (do_mouse(NULL, c, BACKWARD, 1L, 0))
  6244.     {
  6245.     start_arrow(&tpos);
  6246. # ifdef FEAT_CINDENT
  6247.     can_cindent = TRUE;
  6248. # endif
  6249.     }
  6250.  
  6251. #ifdef FEAT_WINDOWS
  6252.     /* redraw status lines (in case another window became active) */
  6253.     redraw_statuslines();
  6254. #endif
  6255. }
  6256.  
  6257.     static void
  6258. ins_mousescroll(up)
  6259.     int        up;
  6260. {
  6261.     pos_T    tpos;
  6262.  
  6263.     undisplay_dollar();
  6264.     tpos = curwin->w_cursor;
  6265.     if (mod_mask & MOD_MASK_SHIFT)
  6266.     scroll_redraw(up, (long)(curwin->w_botline - curwin->w_topline));
  6267.     else
  6268.     scroll_redraw(up, 3L);
  6269.     if (!equal(curwin->w_cursor, tpos))
  6270.     {
  6271.     start_arrow(&tpos);
  6272. # ifdef FEAT_CINDENT
  6273.     can_cindent = TRUE;
  6274. # endif
  6275.     }
  6276. }
  6277. #endif
  6278.  
  6279. #ifdef FEAT_GUI
  6280.     void
  6281. ins_scroll()
  6282. {
  6283.     pos_T    tpos;
  6284.  
  6285.     undisplay_dollar();
  6286.     tpos = curwin->w_cursor;
  6287.     if (gui_do_scroll())
  6288.     {
  6289.     start_arrow(&tpos);
  6290. # ifdef FEAT_CINDENT
  6291.     can_cindent = TRUE;
  6292. # endif
  6293.     }
  6294. }
  6295.  
  6296.     void
  6297. ins_horscroll()
  6298. {
  6299.     pos_T    tpos;
  6300.  
  6301.     undisplay_dollar();
  6302.     tpos = curwin->w_cursor;
  6303.     if (gui_do_horiz_scroll())
  6304.     {
  6305.     start_arrow(&tpos);
  6306. # ifdef FEAT_CINDENT
  6307.     can_cindent = TRUE;
  6308. # endif
  6309.     }
  6310. }
  6311. #endif
  6312.  
  6313.     static void
  6314. ins_left()
  6315. {
  6316.     pos_T    tpos;
  6317.  
  6318. #ifdef FEAT_FOLDING
  6319.     if ((fdo_flags & FDO_HOR) && KeyTyped)
  6320.     foldOpenCursor();
  6321. #endif
  6322.     undisplay_dollar();
  6323.     tpos = curwin->w_cursor;
  6324.     if (oneleft() == OK)
  6325.     {
  6326.     start_arrow(&tpos);
  6327. #ifdef FEAT_RIGHTLEFT
  6328.     /* If exit reversed string, position is fixed */
  6329.     if (revins_scol != -1 && (int)curwin->w_cursor.col >= revins_scol)
  6330.         revins_legal++;
  6331.     revins_chars++;
  6332. #endif
  6333.     }
  6334.  
  6335.     /*
  6336.      * if 'whichwrap' set for cursor in insert mode may go to
  6337.      * previous line
  6338.      */
  6339.     else if (vim_strchr(p_ww, '[') != NULL && curwin->w_cursor.lnum > 1)
  6340.     {
  6341.     start_arrow(&tpos);
  6342.     --(curwin->w_cursor.lnum);
  6343.     coladvance((colnr_T)MAXCOL);
  6344.     curwin->w_set_curswant = TRUE;    /* so we stay at the end */
  6345.     }
  6346.     else
  6347.     vim_beep();
  6348. }
  6349.  
  6350.     static void
  6351. ins_home(c)
  6352.     int        c;
  6353. {
  6354.     pos_T    tpos;
  6355.  
  6356. #ifdef FEAT_FOLDING
  6357.     if ((fdo_flags & FDO_HOR) && KeyTyped)
  6358.     foldOpenCursor();
  6359. #endif
  6360.     undisplay_dollar();
  6361.     tpos = curwin->w_cursor;
  6362.     if (c == K_C_HOME)
  6363.     curwin->w_cursor.lnum = 1;
  6364.     curwin->w_cursor.col = 0;
  6365. #ifdef FEAT_VIRTUALEDIT
  6366.     curwin->w_cursor.coladd = 0;
  6367. #endif
  6368.     curwin->w_curswant = 0;
  6369.     start_arrow(&tpos);
  6370. }
  6371.  
  6372.     static void
  6373. ins_end(c)
  6374.     int        c;
  6375. {
  6376.     pos_T    tpos;
  6377.  
  6378. #ifdef FEAT_FOLDING
  6379.     if ((fdo_flags & FDO_HOR) && KeyTyped)
  6380.     foldOpenCursor();
  6381. #endif
  6382.     undisplay_dollar();
  6383.     tpos = curwin->w_cursor;
  6384.     if (c == K_C_END)
  6385.     curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
  6386.     coladvance((colnr_T)MAXCOL);
  6387.     curwin->w_curswant = MAXCOL;
  6388.  
  6389.     start_arrow(&tpos);
  6390. }
  6391.  
  6392.     static void
  6393. ins_s_left()
  6394. {
  6395. #ifdef FEAT_FOLDING
  6396.     if ((fdo_flags & FDO_HOR) && KeyTyped)
  6397.     foldOpenCursor();
  6398. #endif
  6399.     undisplay_dollar();
  6400.     if (curwin->w_cursor.lnum > 1 || curwin->w_cursor.col > 0)
  6401.     {
  6402.     start_arrow(&curwin->w_cursor);
  6403.     (void)bck_word(1L, FALSE, FALSE);
  6404.     curwin->w_set_curswant = TRUE;
  6405.     }
  6406.     else
  6407.     vim_beep();
  6408. }
  6409.  
  6410.     static void
  6411. ins_right()
  6412. {
  6413. #ifdef FEAT_FOLDING
  6414.     if ((fdo_flags & FDO_HOR) && KeyTyped)
  6415.     foldOpenCursor();
  6416. #endif
  6417.     undisplay_dollar();
  6418.     if (gchar_cursor() != NUL || virtual_active()
  6419.         )
  6420.     {
  6421.     start_arrow(&curwin->w_cursor);
  6422.     curwin->w_set_curswant = TRUE;
  6423. #ifdef FEAT_VIRTUALEDIT
  6424.     if (virtual_active())
  6425.         oneright();
  6426.     else
  6427. #endif
  6428.     {
  6429. #ifdef FEAT_MBYTE
  6430.         if (has_mbyte)
  6431.         curwin->w_cursor.col += (*mb_ptr2len_check)(ml_get_cursor());
  6432.         else
  6433. #endif
  6434.         ++curwin->w_cursor.col;
  6435.     }
  6436.  
  6437. #ifdef FEAT_RIGHTLEFT
  6438.     revins_legal++;
  6439.     if (revins_chars)
  6440.         revins_chars--;
  6441. #endif
  6442.     }
  6443.     /* if 'whichwrap' set for cursor in insert mode, may move the
  6444.      * cursor to the next line */
  6445.     else if (vim_strchr(p_ww, ']') != NULL
  6446.         && curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count)
  6447.     {
  6448.     start_arrow(&curwin->w_cursor);
  6449.     curwin->w_set_curswant = TRUE;
  6450.     ++curwin->w_cursor.lnum;
  6451.     curwin->w_cursor.col = 0;
  6452.     }
  6453.     else
  6454.     vim_beep();
  6455. }
  6456.  
  6457.     static void
  6458. ins_s_right()
  6459. {
  6460. #ifdef FEAT_FOLDING
  6461.     if ((fdo_flags & FDO_HOR) && KeyTyped)
  6462.     foldOpenCursor();
  6463. #endif
  6464.     undisplay_dollar();
  6465.     if (curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count
  6466.         || gchar_cursor() != NUL)
  6467.     {
  6468.     start_arrow(&curwin->w_cursor);
  6469.     (void)fwd_word(1L, FALSE, 0);
  6470.     curwin->w_set_curswant = TRUE;
  6471.     }
  6472.     else
  6473.     vim_beep();
  6474. }
  6475.  
  6476.     static void
  6477. ins_up(startcol)
  6478.     int        startcol;    /* when TRUE move to Insstart.col */
  6479. {
  6480.     pos_T    tpos;
  6481.     linenr_T    old_topline = curwin->w_topline;
  6482. #ifdef FEAT_DIFF
  6483.     int        old_topfill = curwin->w_topfill;
  6484. #endif
  6485.  
  6486.     undisplay_dollar();
  6487.     tpos = curwin->w_cursor;
  6488.     if (cursor_up(1L, TRUE) == OK)
  6489.     {
  6490.     if (startcol)
  6491.         coladvance(getvcol_nolist(&Insstart));
  6492.     if (old_topline != curwin->w_topline
  6493. #ifdef FEAT_DIFF
  6494.         || old_topfill != curwin->w_topfill
  6495. #endif
  6496.         )
  6497.         redraw_later(VALID);
  6498.     start_arrow(&tpos);
  6499. #ifdef FEAT_CINDENT
  6500.     can_cindent = TRUE;
  6501. #endif
  6502.     }
  6503.     else
  6504.     vim_beep();
  6505. }
  6506.  
  6507.     static void
  6508. ins_pageup()
  6509. {
  6510.     pos_T    tpos;
  6511.  
  6512.     undisplay_dollar();
  6513.     tpos = curwin->w_cursor;
  6514.     if (onepage(BACKWARD, 1L) == OK)
  6515.     {
  6516.     start_arrow(&tpos);
  6517. #ifdef FEAT_CINDENT
  6518.     can_cindent = TRUE;
  6519. #endif
  6520.     }
  6521.     else
  6522.     vim_beep();
  6523. }
  6524.  
  6525.     static void
  6526. ins_down(startcol)
  6527.     int        startcol;    /* when TRUE move to Insstart.col */
  6528. {
  6529.     pos_T    tpos;
  6530.     linenr_T    old_topline = curwin->w_topline;
  6531. #ifdef FEAT_DIFF
  6532.     int        old_topfill = curwin->w_topfill;
  6533. #endif
  6534.  
  6535.     undisplay_dollar();
  6536.     tpos = curwin->w_cursor;
  6537.     if (cursor_down(1L, TRUE) == OK)
  6538.     {
  6539.     if (startcol)
  6540.         coladvance(getvcol_nolist(&Insstart));
  6541.     if (old_topline != curwin->w_topline
  6542. #ifdef FEAT_DIFF
  6543.         || old_topfill != curwin->w_topfill
  6544. #endif
  6545.         )
  6546.         redraw_later(VALID);
  6547.     start_arrow(&tpos);
  6548. #ifdef FEAT_CINDENT
  6549.     can_cindent = TRUE;
  6550. #endif
  6551.     }
  6552.     else
  6553.     vim_beep();
  6554. }
  6555.  
  6556.     static void
  6557. ins_pagedown()
  6558. {
  6559.     pos_T    tpos;
  6560.  
  6561.     undisplay_dollar();
  6562.     tpos = curwin->w_cursor;
  6563.     if (onepage(FORWARD, 1L) == OK)
  6564.     {
  6565.     start_arrow(&tpos);
  6566. #ifdef FEAT_CINDENT
  6567.     can_cindent = TRUE;
  6568. #endif
  6569.     }
  6570.     else
  6571.     vim_beep();
  6572. }
  6573.  
  6574. /*
  6575.  * Handle TAB in Insert or Replace mode.
  6576.  * Return TRUE when the TAB needs to be inserted like a normal character.
  6577.  */
  6578.     static int
  6579. ins_tab()
  6580. {
  6581.     int        ind;
  6582.     int        i;
  6583.     int        temp;
  6584.  
  6585.     if (Insstart_blank_vcol == MAXCOL && curwin->w_cursor.lnum == Insstart.lnum)
  6586.     Insstart_blank_vcol = get_nolist_virtcol();
  6587.     if (echeck_abbr(TAB + ABBR_OFF))
  6588.     return FALSE;
  6589.  
  6590.     ind = inindent(0);
  6591. #ifdef FEAT_CINDENT
  6592.     if (ind)
  6593.     can_cindent = FALSE;
  6594. #endif
  6595.  
  6596.     /*
  6597.      * When nothing special, insert TAB like a normal character
  6598.      */
  6599.     if (!curbuf->b_p_et
  6600.         && !(p_sta && ind && curbuf->b_p_ts != curbuf->b_p_sw)
  6601.         && curbuf->b_p_sts == 0)
  6602.     return TRUE;
  6603.  
  6604.     if (stop_arrow() == FAIL)
  6605.     return TRUE;
  6606.  
  6607.     did_ai = FALSE;
  6608. #ifdef FEAT_SMARTINDENT
  6609.     did_si = FALSE;
  6610.     can_si = FALSE;
  6611.     can_si_back = FALSE;
  6612. #endif
  6613.     AppendToRedobuff((char_u *)"\t");
  6614.  
  6615.     if (p_sta && ind)        /* insert tab in indent, use 'shiftwidth' */
  6616.     temp = (int)curbuf->b_p_sw;
  6617.     else if (curbuf->b_p_sts > 0) /* use 'softtabstop' when set */
  6618.     temp = (int)curbuf->b_p_sts;
  6619.     else            /* otherwise use 'tabstop' */
  6620.     temp = (int)curbuf->b_p_ts;
  6621.     temp -= get_nolist_virtcol() % temp;
  6622.  
  6623.     /*
  6624.      * Insert the first space with ins_char().    It will delete one char in
  6625.      * replace mode.  Insert the rest with ins_str(); it will not delete any
  6626.      * chars.  For VREPLACE mode, we use ins_char() for all characters.
  6627.      */
  6628.     ins_char(' ');
  6629.     while (--temp > 0)
  6630.     {
  6631. #ifdef FEAT_VREPLACE
  6632.     if (State & VREPLACE_FLAG)
  6633.         ins_char(' ');
  6634.     else
  6635. #endif
  6636.     {
  6637.         ins_str((char_u *)" ");
  6638.         if (State & REPLACE_FLAG)        /* no char replaced */
  6639.         replace_push(NUL);
  6640.     }
  6641.     }
  6642.  
  6643.     /*
  6644.      * When 'expandtab' not set: Replace spaces by TABs where possible.
  6645.      */
  6646.     if (!curbuf->b_p_et && (curbuf->b_p_sts || (p_sta && ind)))
  6647.     {
  6648.     char_u        *ptr;
  6649. #ifdef FEAT_VREPLACE
  6650.     char_u        *saved_line = NULL;    /* init for GCC */
  6651.     pos_T        pos;
  6652. #endif
  6653.     pos_T        fpos;
  6654.     pos_T        *cursor;
  6655.     colnr_T        want_vcol, vcol;
  6656.     int        change_col = -1;
  6657.  
  6658.     /*
  6659.      * Get the current line.  For VREPLACE mode, don't make real changes
  6660.      * yet, just work on a copy of the line.
  6661.      */
  6662. #ifdef FEAT_VREPLACE
  6663.     if (State & VREPLACE_FLAG)
  6664.     {
  6665.         pos = curwin->w_cursor;
  6666.         cursor = &pos;
  6667.         saved_line = vim_strsave(ml_get_curline());
  6668.         if (saved_line == NULL)
  6669.         return FALSE;
  6670.         ptr = saved_line + pos.col;
  6671.     }
  6672.     else
  6673. #endif
  6674.     {
  6675.         ptr = ml_get_cursor();
  6676.         cursor = &curwin->w_cursor;
  6677.     }
  6678.  
  6679.     /* Find first white before the cursor */
  6680.     fpos = curwin->w_cursor;
  6681.     while (fpos.col > 0 && vim_iswhite(ptr[-1]))
  6682.     {
  6683.         --fpos.col;
  6684.         --ptr;
  6685.     }
  6686.  
  6687.     /* In Replace mode, don't change characters before the insert point. */
  6688.     if ((State & REPLACE_FLAG)
  6689.         && fpos.lnum == Insstart.lnum
  6690.         && fpos.col < Insstart.col)
  6691.     {
  6692.         ptr += Insstart.col - fpos.col;
  6693.         fpos.col = Insstart.col;
  6694.     }
  6695.  
  6696.     /* compute virtual column numbers of first white and cursor */
  6697.     getvcol(curwin, &fpos, &vcol, NULL, NULL);
  6698.     getvcol(curwin, cursor, &want_vcol, NULL, NULL);
  6699.  
  6700.     /* Use as many TABs as possible.  Beware of 'showbreak' and
  6701.      * 'linebreak' adding extra virtual columns. */
  6702.     while (vim_iswhite(*ptr))
  6703.     {
  6704.         i = lbr_chartabsize((char_u *)"\t", vcol);
  6705.         if (vcol + i > want_vcol)
  6706.         break;
  6707.         if (*ptr != TAB)
  6708.         {
  6709.         *ptr = TAB;
  6710.         if (change_col < 0)
  6711.         {
  6712.             change_col = fpos.col;  /* Column of first change */
  6713.             /* May have to adjust Insstart */
  6714.             if (fpos.lnum == Insstart.lnum && fpos.col < Insstart.col)
  6715.             Insstart.col = fpos.col;
  6716.         }
  6717.         }
  6718.         ++fpos.col;
  6719.         ++ptr;
  6720.         vcol += i;
  6721.     }
  6722.  
  6723.     if (change_col >= 0)
  6724.     {
  6725.         int repl_off = 0;
  6726.  
  6727.         /* Skip over the spaces we need. */
  6728.         while (vcol < want_vcol && *ptr == ' ')
  6729.         {
  6730.         vcol += lbr_chartabsize(ptr, vcol);
  6731.         ++ptr;
  6732.         ++repl_off;
  6733.         }
  6734.         if (vcol > want_vcol)
  6735.         {
  6736.         /* Must have a char with 'showbreak' just before it. */
  6737.         --ptr;
  6738.         --repl_off;
  6739.         }
  6740.         fpos.col += repl_off;
  6741.  
  6742.         /* Delete following spaces. */
  6743.         i = cursor->col - fpos.col;
  6744.         if (i > 0)
  6745.         {
  6746.         mch_memmove(ptr, ptr + i, STRLEN(ptr + i) + 1);
  6747.         /* correct replace stack. */
  6748.         if ((State & REPLACE_FLAG)
  6749. #ifdef FEAT_VREPLACE
  6750.             && !(State & VREPLACE_FLAG)
  6751. #endif
  6752.             )
  6753.             for (temp = i; --temp >= 0; )
  6754.             replace_join(repl_off);
  6755.         }
  6756.         cursor->col -= i;
  6757.  
  6758. #ifdef FEAT_VREPLACE
  6759.         /*
  6760.          * In VREPLACE mode, we haven't changed anything yet.  Do it now by
  6761.          * backspacing over the changed spacing and then inserting the new
  6762.          * spacing.
  6763.          */
  6764.         if (State & VREPLACE_FLAG)
  6765.         {
  6766.         /* Backspace from real cursor to change_col */
  6767.         backspace_until_column(change_col);
  6768.  
  6769.         /* Insert each char in saved_line from changed_col to
  6770.          * ptr-cursor */
  6771.         ins_bytes_len(saved_line + change_col,
  6772.                             cursor->col - change_col);
  6773.         }
  6774. #endif
  6775.     }
  6776.  
  6777. #ifdef FEAT_VREPLACE
  6778.     if (State & VREPLACE_FLAG)
  6779.         vim_free(saved_line);
  6780. #endif
  6781.     }
  6782.  
  6783.     return FALSE;
  6784. }
  6785.  
  6786. /*
  6787.  * Handle CR or NL in insert mode.
  6788.  * Return TRUE when out of memory or can't undo.
  6789.  */
  6790.     static int
  6791. ins_eol(c)
  6792.     int        c;
  6793. {
  6794.     int        i;
  6795.  
  6796.     if (echeck_abbr(c + ABBR_OFF))
  6797.     return FALSE;
  6798.     if (stop_arrow() == FAIL)
  6799.     return TRUE;
  6800.     undisplay_dollar();
  6801.  
  6802.     /*
  6803.      * Strange Vi behaviour: In Replace mode, typing a NL will not delete the
  6804.      * character under the cursor.  Only push a NUL on the replace stack,
  6805.      * nothing to put back when the NL is deleted.
  6806.      */
  6807.     if ((State & REPLACE_FLAG)
  6808. #ifdef FEAT_VREPLACE
  6809.         && !(State & VREPLACE_FLAG)
  6810. #endif
  6811.         )
  6812.     replace_push(NUL);
  6813.  
  6814.     /*
  6815.      * In VREPLACE mode, a NL replaces the rest of the line, and starts
  6816.      * replacing the next line, so we push all of the characters left on the
  6817.      * line onto the replace stack.  This is not done here though, it is done
  6818.      * in open_line().
  6819.      */
  6820.  
  6821. #ifdef FEAT_RIGHTLEFT
  6822. # ifdef FEAT_FKMAP
  6823.     if (p_altkeymap && p_fkmap)
  6824.     fkmap(NL);
  6825. # endif
  6826.     /* NL in reverse insert will always start in the end of
  6827.      * current line. */
  6828.     if (revins_on)
  6829.     curwin->w_cursor.col += (colnr_T)STRLEN(ml_get_cursor());
  6830. #endif
  6831.  
  6832.     AppendToRedobuff(NL_STR);
  6833.     i = open_line(FORWARD,
  6834. #ifdef FEAT_COMMENTS
  6835.         has_format_option(FO_RET_COMS) ? OPENLINE_DO_COM :
  6836. #endif
  6837.         0, old_indent);
  6838.     old_indent = 0;
  6839. #ifdef FEAT_CINDENT
  6840.     can_cindent = TRUE;
  6841. #endif
  6842.  
  6843.     return (!i);
  6844. }
  6845.  
  6846. #ifdef FEAT_DIGRAPHS
  6847. /*
  6848.  * Handle digraph in insert mode.
  6849.  * Returns character still to be inserted, or NUL when nothing remaining to be
  6850.  * done.
  6851.  */
  6852.     static int
  6853. ins_digraph()
  6854. {
  6855.     int        c;
  6856.     int        cc;
  6857.  
  6858.     if (redrawing() && !char_avail())
  6859.     {
  6860.     /* may need to redraw when no more chars available now */
  6861.     ins_redraw();
  6862.  
  6863.     edit_putchar('?', TRUE);
  6864. #ifdef FEAT_CMDL_INFO
  6865.     add_to_showcmd_c(Ctrl_K);
  6866. #endif
  6867.     }
  6868.  
  6869. #ifdef USE_ON_FLY_SCROLL
  6870.     dont_scroll = TRUE;        /* disallow scrolling here */
  6871. #endif
  6872.  
  6873.     /* don't map the digraph chars. This also prevents the
  6874.      * mode message to be deleted when ESC is hit */
  6875.     ++no_mapping;
  6876.     ++allow_keys;
  6877.     c = safe_vgetc();
  6878.     --no_mapping;
  6879.     --allow_keys;
  6880.     if (IS_SPECIAL(c) || mod_mask)        /* special key */
  6881.     {
  6882. #ifdef FEAT_CMDL_INFO
  6883.     clear_showcmd();
  6884. #endif
  6885.     insert_special(c, TRUE, FALSE);
  6886.     return NUL;
  6887.     }
  6888.     if (c != ESC)
  6889.     {
  6890.     if (redrawing() && !char_avail())
  6891.     {
  6892.         /* may need to redraw when no more chars available now */
  6893.         ins_redraw();
  6894.  
  6895.         if (char2cells(c) == 1)
  6896.         edit_putchar(c, TRUE);
  6897. #ifdef FEAT_CMDL_INFO
  6898.         add_to_showcmd_c(c);
  6899. #endif
  6900.     }
  6901.     ++no_mapping;
  6902.     ++allow_keys;
  6903.     cc = safe_vgetc();
  6904.     --no_mapping;
  6905.     --allow_keys;
  6906.     if (cc != ESC)
  6907.     {
  6908.         AppendToRedobuff((char_u *)CTRL_V_STR);
  6909.         c = getdigraph(c, cc, TRUE);
  6910. #ifdef FEAT_CMDL_INFO
  6911.         clear_showcmd();
  6912. #endif
  6913.         return c;
  6914.     }
  6915.     }
  6916.     edit_unputchar();
  6917. #ifdef FEAT_CMDL_INFO
  6918.     clear_showcmd();
  6919. #endif
  6920.     return NUL;
  6921. }
  6922. #endif
  6923.  
  6924. /*
  6925.  * Handle CTRL-E and CTRL-Y in Insert mode: copy char from other line.
  6926.  * Returns the char to be inserted, or NUL if none found.
  6927.  */
  6928.     static int
  6929. ins_copychar(lnum)
  6930.     linenr_T    lnum;
  6931. {
  6932.     int        c;
  6933.     int        temp;
  6934.     char_u  *ptr, *prev_ptr;
  6935.  
  6936.     if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count)
  6937.     {
  6938.     vim_beep();
  6939.     return NUL;
  6940.     }
  6941.  
  6942.     /* try to advance to the cursor column */
  6943.     temp = 0;
  6944.     ptr = ml_get(lnum);
  6945.     prev_ptr = ptr;
  6946.     validate_virtcol();
  6947.     while ((colnr_T)temp < curwin->w_virtcol && *ptr != NUL)
  6948.     {
  6949.     prev_ptr = ptr;
  6950.     temp += lbr_chartabsize_adv(&ptr, (colnr_T)temp);
  6951.     }
  6952.     if ((colnr_T)temp > curwin->w_virtcol)
  6953.     ptr = prev_ptr;
  6954.  
  6955. #ifdef FEAT_MBYTE
  6956.     c = (*mb_ptr2char)(ptr);
  6957. #else
  6958.     c = *ptr;
  6959. #endif
  6960.     if (c == NUL)
  6961.     vim_beep();
  6962.     return c;
  6963. }
  6964.  
  6965. #ifdef FEAT_SMARTINDENT
  6966. /*
  6967.  * Try to do some very smart auto-indenting.
  6968.  * Used when inserting a "normal" character.
  6969.  */
  6970.     static void
  6971. ins_try_si(c)
  6972.     int        c;
  6973. {
  6974.     pos_T    *pos, old_pos;
  6975.     char_u    *ptr;
  6976.     int        i;
  6977.     int        temp;
  6978.  
  6979.     /*
  6980.      * do some very smart indenting when entering '{' or '}'
  6981.      */
  6982.     if (((did_si || can_si_back) && c == '{') || (can_si && c == '}'))
  6983.     {
  6984.     /*
  6985.      * for '}' set indent equal to indent of line containing matching '{'
  6986.      */
  6987.     if (c == '}' && (pos = findmatch(NULL, '{')) != NULL)
  6988.     {
  6989.         old_pos = curwin->w_cursor;
  6990.         /*
  6991.          * If the matching '{' has a ')' immediately before it (ignoring
  6992.          * white-space), then line up with the start of the line
  6993.          * containing the matching '(' if there is one.  This handles the
  6994.          * case where an "if (..\n..) {" statement continues over multiple
  6995.          * lines -- webb
  6996.          */
  6997.         ptr = ml_get(pos->lnum);
  6998.         i = pos->col;
  6999.         if (i > 0)        /* skip blanks before '{' */
  7000.         while (--i > 0 && vim_iswhite(ptr[i]))
  7001.             ;
  7002.         curwin->w_cursor.lnum = pos->lnum;
  7003.         curwin->w_cursor.col = i;
  7004.         if (ptr[i] == ')' && (pos = findmatch(NULL, '(')) != NULL)
  7005.         curwin->w_cursor = *pos;
  7006.         i = get_indent();
  7007.         curwin->w_cursor = old_pos;
  7008. #ifdef FEAT_VREPLACE
  7009.         if (State & VREPLACE_FLAG)
  7010.         change_indent(INDENT_SET, i, FALSE, NUL);
  7011.         else
  7012. #endif
  7013.         (void)set_indent(i, SIN_CHANGED);
  7014.     }
  7015.     else if (curwin->w_cursor.col > 0)
  7016.     {
  7017.         /*
  7018.          * when inserting '{' after "O" reduce indent, but not
  7019.          * more than indent of previous line
  7020.          */
  7021.         temp = TRUE;
  7022.         if (c == '{' && can_si_back && curwin->w_cursor.lnum > 1)
  7023.         {
  7024.         old_pos = curwin->w_cursor;
  7025.         i = get_indent();
  7026.         while (curwin->w_cursor.lnum > 1)
  7027.         {
  7028.             ptr = skipwhite(ml_get(--(curwin->w_cursor.lnum)));
  7029.  
  7030.             /* ignore empty lines and lines starting with '#'. */
  7031.             if (*ptr != '#' && *ptr != NUL)
  7032.             break;
  7033.         }
  7034.         if (get_indent() >= i)
  7035.             temp = FALSE;
  7036.         curwin->w_cursor = old_pos;
  7037.         }
  7038.         if (temp)
  7039.         shift_line(TRUE, FALSE, 1);
  7040.     }
  7041.     }
  7042.  
  7043.     /*
  7044.      * set indent of '#' always to 0
  7045.      */
  7046.     if (curwin->w_cursor.col > 0 && can_si && c == '#')
  7047.     {
  7048.     /* remember current indent for next line */
  7049.     old_indent = get_indent();
  7050.     (void)set_indent(0, SIN_CHANGED);
  7051.     }
  7052.  
  7053.     /* Adjust ai_col, the char at this position can be deleted. */
  7054.     if (ai_col > curwin->w_cursor.col)
  7055.     ai_col = curwin->w_cursor.col;
  7056. }
  7057. #endif
  7058.  
  7059. /*
  7060.  * Get the value that w_virtcol would have when 'list' is off.
  7061.  * Unless 'cpo' contains the 'L' flag.
  7062.  */
  7063.     static colnr_T
  7064. get_nolist_virtcol()
  7065. {
  7066.     if (curwin->w_p_list && vim_strchr(p_cpo, CPO_LISTWM) == NULL)
  7067.     return getvcol_nolist(&curwin->w_cursor);
  7068.     validate_virtcol();
  7069.     return curwin->w_virtcol;
  7070. }
  7071.